How to update record using Entity Framework 6?
Asked Answered
O

20

329

I am trying to update a record using EF6. First finding the record, if it exists, update. Here is my code:

var book = new Model.Book
{
    BookNumber =  _book.BookNumber,
    BookName = _book.BookName,
    BookTitle = _book.BookTitle,
};
using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        try
        {
            db.Books.Attach(book);
            db.Entry(book).State = EntityState.Modified;
            db.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

Every time I try to update the record using the above code, I am getting this error:

{System.Data.Entity.Infrastructure.DbUpdateConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries

Octoroon answered 17/9, 2014 at 15:26 Comment(9)
Side note: catch (Exception ex){throw;} is redundant and you can completely remove it.Amendatory
try catch block is just to figure out the reason of failing. But Still did not get it why this code is failing?Octoroon
Am not expert in this topic, I can't answer this question. but without try catch also you can use break when exception is thrown feature to break the debugger when there is an exception.Amendatory
If you search the web or this site for that error, you get many hints. Which ones did you find and what did you try? What does your table look like?Needful
@CodeCaster: My table does not have any constraint of NOT NULL (except primary key, which is set to auto incremental). Checked in sql profiler too, If run same query manually, it works.Octoroon
My Model type is Database-First.Octoroon
You haven't changed anything. Playing with Entity state won't change the fact that the object hasn't actually been modified.Birdt
Well, I did the same as you and didn't get the error. The Exception says DbUpdateConcurrencyException. How did you handle the concurrency? Did you use a timestamp, did you clone and then merge the objects again or did you use self-tracking entities? (3 most used approaches). If you didn't handle the concurrency, I guess that's the problem.Jacobite
How is it that none of the comments/answers here homes in on whether the book object has a valid primary key value? Because it hasn't. If it had, it couldn't have been attached after result was found. That's the cause of the DbUpdateConcurrencyException. Maybe this answer does a half-baked attempt addressing the flaw, but it doesn't really explain much.Nasya
M
446

You're trying to update the record (which to me means "change a value on an existing record and save it back"). So you need to retrieve the object, make a change, and save it.

using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        result.SomeValue = "Some new value";
        db.SaveChanges();
    }
}
Muldrow answered 17/9, 2014 at 18:51 Comment(12)
W, how does this exactly work? how does assinging a value to "result", actually updates the database?Preparation
Assigning the value doesn't update the database, calling db.SaveChanges() with modified objects in the context updates the database.Muldrow
Still it fascinates me... so var result, actually becomes connected to the dbcontext... so this means that any variable that is instantiated by any dbcontext members will actually have that associaten to the database so that whatever changes is applied to that variable, it is also applied or persisted?Preparation
Because the context generated the object the context can track the object, including changes to the object. When you call SaveChanges the context evaluates all the objects it is tracking to determine if they are added, changed, or deleted and issues the appropriate SQL to the connected database.Muldrow
iam facing same issue - using EF6 , trying to update an entity. Attach + EntityState.Modified not working . Only thing working is - you need to retrieve the object, make desired changes, and save it via db.SaveChanges();Pretentious
Is this query same ? , var result = db.Books.Where(b => b.BookNumber == bookNumber).SingleOrDefault(); and is there any performance consideration between FirstOrDefault and SingleOrDefault ?Sabelle
@stom: Yes, the query is the same in the sense that it will return the same result. You'd have to test it to see if there's a performance difference in your specific situation.Muldrow
You should NOT have to retrieve the object first in order to update it. I had the same problem until I realized I was trying to change one of the primary key values (composite key). As long as you provide a correct primary key, you can set the EntityState to Modified and SaveChanges() will work, provided you don't break some other integrity constraint defined on the table.Skippie
@CraigW., I am doing a similar thing but instead of updating, its adding a new entry for me. Any ideas why? #51509230Nova
The result is passed by reference, that's why this works :)Lawsuit
When you pull the item using line 3 it automatically sets it up for change tracking. That is why this works. To do it the other way you need to not load it for change tracking ( omit line 3 ) attach, set state to Modified and then save changes.It's all based on knowing when something is set for change tracking.Lohrman
If you do anything to set context.Configuration.AutoDetectChangesEnabled to false, you'll need to set it back to true before this will work. I changed it to false for BulkInsert to work faster and I didn't see any updates using this method until I changed it back to true before making the changes.Juster
S
242

I have been reviewing the source code of Entity Framework and found a way to actually update an entity if you know the Key property:

public void Update<T>(T item) where T: Entity
{
    // assume Entity base class have an Id property for all items
    var entity = _collection.Find(item.Id);
    if (entity == null)
    {
        return;
    }

    _context.Entry(entity).CurrentValues.SetValues(item);
}

Otherwise, check the AddOrUpdate implementation for ideas.

Hope this help!

Selfdelusion answered 18/4, 2016 at 2:45 Comment(17)
Nice! No need to enumerate all properties. I assume SaveChanges() call is required after setting values.Cheesecloth
Yes, changes will be persisted on SaveChanges()Selfdelusion
Great answer, it was not too clear with IntelliSense that doing something like this would NOT work: _context.MyObj = newObj; then SaveChanges() or.... _context.MyObj.Update(newObj) then SaveChanges(); Your solution updates the whole object without having to loop through all the properties.Clean
This complains to me that I'm trying to edit the ID fieldIlyse
@Selfdelusion What references do you need to run this? I'm getting the following errors: T does not contain a definition for Id _collection does not exist in the current contextAnguilla
T is a generic parameter, use your entity class instead: User, Order, ...Selfdelusion
@VasilyHall - this occurs if the ID fields (or whatever you have defined the Primary Key as) are different between models (including null / 0 in one of the models). Make sure the IDs match between the two models and it will update just fine.Homelike
Wow life changing. I did have to do the following before I set the values to keep the primary keys the same... entity.Id = existingEntity.Id;Missing
@Selfdelusion - Can you update your answer with the ID comments here? Tripped me up for a while before I read them.Diplegia
What is _collection here?Frederickson
@Frederickson The _collection variable is a DbSet<T>Selfdelusion
This code is trying to update all the values irrespective of the null entries. I want the values in the old object to be retained in a case where new values not supplied. IS: I want only the non-empty values to be updated !Heise
Any help would be appreciatedHeise
@Heise I haven't done what you suggest but the whole idea of the method is that you have a valid entity to update from. If the entity you are passing has some null properties that aren't null in the DB your are getting out of sync or setting the properties to null explicit in your codeSelfdelusion
@Toolkit Please provide a better approach to retrieve the current entity within the EF boundaries. This will trigger a select if your entity is not in memory. Must of the time it will be or you will reuse after that. Anyway, this select will have a where clause on the key (which is indexed) I can think of a faster way to retrieve the db value at the time. The fact you think is amateurish it is good, please enlighten us with the truth.Selfdelusion
This throws a Member 'CurrentValues' cannot be called for the entity of type 'Entity' because the entity does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Entity>. error on the 2nd to last line for meBoracic
@Boracic did you modified the query line (var entity = _collection.Find(item.Id);) or the entity don't exists already? This is an update method meant to update an existing entity.Selfdelusion
H
54

You can use the AddOrUpdate method:

db.Books.AddOrUpdate(book); //requires using System.Data.Entity.Migrations;
db.SaveChanges();
Hilariahilario answered 12/10, 2016 at 16:17 Comment(6)
IMO best solutionGustafson
.AddOrUpdate() is used during database migration, it is highly discouraged to use this method outside of migrations, hence why it's in the Entity.Migrations namespace.Semiotic
I did reverse engineering on this AddOrUpdate code and the results are my other answer. #25895087Selfdelusion
As @AdamVincent said, AddOrUpdate() method is intended for migrations and it's not suitable for situation when you need only to update existing row. In case when you don't have book with search reference (i.e. ID) it'll create new row and it can be an issue in come cases (for example, you have an API which needs to return you 404-NotFound response if you try to call PUT method for non-existing row).Broyles
Don;t use this unless you know what you are doing!!!!!!!!!!!!!!!! read: michaelgmccarthy.com/2016/08/24/…Fluky
I came back to this again today, can I just warn you all that this is not a good solution for the desired use caseFluky
V
32

So you have an entity that is updated, and you want to update it in the database with the least amount of code...

Concurrency is always tricky, but I am assuming that you just want your updates to win. Here is how I did it for my same case and modified the names to mimic your classes. In other words, just change attach to add, and it works for me:

public static void SaveBook(Model.Book myBook)
{
    using (var ctx = new BookDBContext())
    {
        ctx.Books.Add(myBook);
        ctx.Entry(myBook).State = System.Data.Entity.EntityState.Modified;
        ctx.SaveChanges();
    }
}
Vikki answered 12/5, 2017 at 17:23 Comment(0)
E
20

You should use the Entry() method in case you want to update all the fields in your object. Also keep in mind you cannot change the field id (key) therefore first set the Id to the same as you edit.

using(var context = new ...())
{
    var EditedObj = context
        .Obj
        .Where(x => x. ....)
        .First();

    NewObj.Id = EditedObj.Id; //This is important when we first create an object (NewObj), in which the default Id = 0. We can not change an existing key.

    context.Entry(EditedObj).CurrentValues.SetValues(NewObj);

    context.SaveChanges();
}
Endoblast answered 16/11, 2017 at 23:27 Comment(2)
You should at least try to answer the question, not just post the codeElegize
Please make some explanation to the question instead of just leaving a code snippet in order to help the question asker better.Charlotte
S
19

Attaching an entity will set its tracking state to Unchanged. To update an existing entity, all you need to do is set the tracking state to Modified. According to the EF6 docs:

If you have an entity that you know already exists in the database but to which changes may have been made then you can tell the context to attach the entity and set its state to Modified. For example:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Modified;

    // Do some more work...  

    context.SaveChanges();
}
Samy answered 12/6, 2019 at 13:8 Comment(1)
Thanks. That is the perfect solution for me as it can save a lots of line of code for updating the attributes of the object. And when Model updates, we also need to update the controller and that's not EF should work.Soares
W
10

I found a way that works just fine.

 var Update = context.UpdateTables.Find(id);
        Update.Title = title;

        // Mark as Changed
        context.Entry(Update).State = System.Data.Entity.EntityState.Modified;
        context.SaveChanges();
Woodrow answered 31/7, 2018 at 15:44 Comment(0)
I
9

This code is the result of a test to update only a set of columns without making a query to return the record first. It uses Entity Framework 7 code first.

// This function receives an object type that can be a view model or an anonymous 
// object with the properties you want to change. 
// This is part of a repository for a Contacts object.

public int Update(object entity)
{
    var entityProperties =  entity.GetType().GetProperties();   
    Contacts con = ToType(entity, typeof(Contacts)) as Contacts;

    if (con != null)
    {
        _context.Entry(con).State = EntityState.Modified;
        _context.Contacts.Attach(con);

        foreach (var ep in entityProperties)
        {
            // If the property is named Id, don't add it in the update. 
            // It can be refactored to look in the annotations for a key 
            // or any part named Id.

            if(ep.Name != "Id")
                _context.Entry(con).Property(ep.Name).IsModified = true;
        }
    }

    return _context.SaveChanges();
}

public static object ToType<T>(object obj, T type)
{
    // Create an instance of T type object
    object tmp = Activator.CreateInstance(Type.GetType(type.ToString()));

    // Loop through the properties of the object you want to convert
    foreach (PropertyInfo pi in obj.GetType().GetProperties())
    {
        try
        {
            // Get the value of the property and try to assign it to the property of T type object
            tmp.GetType().GetProperty(pi.Name).SetValue(tmp, pi.GetValue(obj, null), null);
        }
        catch (Exception ex)
        {
            // Logging.Log.Error(ex);
        }
    }
    // Return the T type object:         
    return tmp;
}

Here is the complete code:

public interface IContactRepository
{
    IEnumerable<Contacts> GetAllContats();
    IEnumerable<Contacts> GetAllContactsWithAddress();
    int Update(object c);
}

public class ContactRepository : IContactRepository
{
    private ContactContext _context;

    public ContactRepository(ContactContext context)
    {
        _context = context;
    }

    public IEnumerable<Contacts> GetAllContats()
    {
        return _context.Contacts.OrderBy(c => c.FirstName).ToList();
    }

    public IEnumerable<Contacts> GetAllContactsWithAddress()
    {
        return _context.Contacts
            .Include(c => c.Address)
            .OrderBy(c => c.FirstName).ToList();
    }   

    //TODO Change properties to lambda expression
    public int Update(object entity)
    {
        var entityProperties = entity.GetType().GetProperties();

        Contacts con = ToType(entity, typeof(Contacts)) as Contacts;

        if (con != null)
        {
            _context.Entry(con).State = EntityState.Modified;
            _context.Contacts.Attach(con);

            foreach (var ep in entityProperties)
            {
                if(ep.Name != "Id")
                    _context.Entry(con).Property(ep.Name).IsModified = true;
            }
        }

        return _context.SaveChanges();
    }

    public static object ToType<T>(object obj, T type)
    {
        // Create an instance of T type object
        object tmp = Activator.CreateInstance(Type.GetType(type.ToString()));

        // Loop through the properties of the object you want to convert
        foreach (PropertyInfo pi in obj.GetType().GetProperties())
        {
            try
            {
                // Get the value of the property and try to assign it to the property of T type object
                tmp.GetType().GetProperty(pi.Name).SetValue(tmp, pi.GetValue(obj, null), null);
            }
            catch (Exception ex)
            {
                // Logging.Log.Error(ex);
            }
        }
        // Return the T type object
        return tmp;
    }
}    

public class Contacts
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Company { get; set; }
    public string Title { get; set; }
    public Addresses Address { get; set; }    
}

public class Addresses
{
    [Key]
    public int Id { get; set; }
    public string AddressType { get; set; }
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public State State { get; set; }
    public string PostalCode { get; set; }  
}

public class ContactContext : DbContext
{
    public DbSet<Addresses> Address { get; set; } 
    public DbSet<Contacts> Contacts { get; set; } 
    public DbSet<State> States { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connString = "Server=YourServer;Database=ContactsDb;Trusted_Connection=True;MultipleActiveResultSets=true;";
        optionsBuilder.UseSqlServer(connString);
        base.OnConfiguring(optionsBuilder);
    }
}
Incorporeal answered 11/1, 2016 at 2:28 Comment(0)
P
9

For .net core

context.Customer.Add(customer);
context.Entry(customer).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
context.SaveChanges();
Pede answered 13/5, 2019 at 15:25 Comment(1)
with this send a proper update or it will send all properties? Suppose I have a record with 10Mb text property. Will it be sending it to DB every time when I update another property?Hangchow
S
5

Here is best solution for this issue: In View add all the ID (Keys). Consider having multiple tables named (First, Second and Third)

@Html.HiddenFor(model=>model.FirstID)
@Html.HiddenFor(model=>model.SecondID)
@Html.HiddenFor(model=>model.Second.SecondID)
@Html.HiddenFor(model=>model.Second.ThirdID)
@Html.HiddenFor(model=>model.Second.Third.ThirdID)

In C# code,

[HttpPost]
public ActionResult Edit(First first)
{
  if (ModelState.Isvalid)
  {
    if (first.FirstID > 0)
    {
      datacontext.Entry(first).State = EntityState.Modified;
      datacontext.Entry(first.Second).State = EntityState.Modified;
      datacontext.Entry(first.Second.Third).State = EntityState.Modified;
    }
    else
    {
      datacontext.First.Add(first);
    }
    datacontext.SaveChanges();
    Return RedirectToAction("Index");
  }

 return View(first);
}
Spec answered 22/12, 2016 at 11:9 Comment(0)
J
4
using(var myDb = new MyDbEntities())
{

    user user = new user();
    user.username = "me";
    user.email = "[email protected]";

    myDb.Users.Add(user);
    myDb.users.Attach(user);
    myDb.Entry(user).State = EntityState.Modified;//this is for modiying/update existing entry
    myDb.SaveChanges();
}
Jacksonjacksonville answered 6/4, 2018 at 3:41 Comment(0)
Y
3

You should remove db.Books.Attach(book);

Yonah answered 2/10, 2016 at 20:2 Comment(0)
I
3

This if for Entity Framework 6.2.0.

If you have a specific DbSet and an item that needs to be either updated or created:

var name = getNameFromService();

var current = _dbContext.Names.Find(name.BusinessSystemId, name.NameNo);
if (current == null)
{
    _dbContext.Names.Add(name);
}
else
{
    _dbContext.Entry(current).CurrentValues.SetValues(name);
}
_dbContext.SaveChanges();

However this can also be used for a generic DbSet with a single primary key or a composite primary key.

var allNames = NameApiService.GetAllNames();
GenericAddOrUpdate(allNames, "BusinessSystemId", "NameNo");

public virtual void GenericAddOrUpdate<T>(IEnumerable<T> values, params string[] keyValues) where T : class
{
    foreach (var value in values)
    {
        try
        {
            var keyList = new List<object>();

            //Get key values from T entity based on keyValues property
            foreach (var keyValue in keyValues)
            {
                var propertyInfo = value.GetType().GetProperty(keyValue);
                var propertyValue = propertyInfo.GetValue(value);
                keyList.Add(propertyValue);
            }

            GenericAddOrUpdateDbSet(keyList, value);
            //Only use this when debugging to catch save exceptions
            //_dbContext.SaveChanges();
        }
        catch
        {
            throw;
        }
    }
    _dbContext.SaveChanges();
}

public virtual void GenericAddOrUpdateDbSet<T>(List<object> keyList, T value) where T : class
{
    //Get a DbSet of T type
    var someDbSet = Set(typeof(T));

    //Check if any value exists with the key values
    var current = someDbSet.Find(keyList.ToArray());
    if (current == null)
    {
        someDbSet.Add(value);
    }
    else
    {
        Entry(current).CurrentValues.SetValues(value);
    }
}
Irisation answered 28/12, 2018 at 16:10 Comment(0)
T
3

The easiest way to do it is like so.

var book = new Model.Book
{
    BookNumber =  _book.BookNumber,
    BookName = _book.BookName,
    BookTitle = _book.BookTitle,
};
using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        try
        {
            // you can't attach book since it doesn't exist in the database yet
            // attach result instead
            db.Books.Attach(result);
            result = book; // this will update all the fields at once
            db.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}
Typecast answered 10/2, 2022 at 16:53 Comment(0)
N
1

Here's my post-RIA entity-update method (for the Ef6 time frame):

public static void UpdateSegment(ISegment data)
{
    if (data == null) throw new ArgumentNullException("The expected Segment data is not here.");

    var context = GetContext();

    var originalData = context.Segments.SingleOrDefault(i => i.SegmentId == data.SegmentId);
    if (originalData == null) throw new NullReferenceException("The expected original Segment data is not here.");

    FrameworkTypeUtility.SetProperties(data, originalData);

    context.SaveChanges();
}

Note that FrameworkTypeUtility.SetProperties() is a tiny utility function I wrote long before AutoMapper on NuGet:

public static void SetProperties<TIn, TOut>(TIn input, TOut output, ICollection<string> includedProperties)
    where TIn : class
    where TOut : class
{
    if ((input == null) || (output == null)) return;
    Type inType = input.GetType();
    Type outType = output.GetType();
    foreach (PropertyInfo info in inType.GetProperties())
    {
        PropertyInfo outfo = ((info != null) && info.CanRead)
            ? outType.GetProperty(info.Name, info.PropertyType)
            : null;
        if (outfo != null && outfo.CanWrite
            && (outfo.PropertyType.Equals(info.PropertyType)))
        {
            if ((includedProperties != null) && includedProperties.Contains(info.Name))
                outfo.SetValue(output, info.GetValue(input, null), null);
            else if (includedProperties == null)
                outfo.SetValue(output, info.GetValue(input, null), null);
        }
    }
}
Nomenclature answered 7/3, 2015 at 3:31 Comment(1)
Note: Works only if your properties are exactly the same in your model as your ViewModel object that is being saved into it.Hendecagon
I
1

Like Renat said, remove: db.Books.Attach(book);

Also, change your result query to use "AsNoTracking", because this query is throwing off entity framework's model state. It thinks "result" is the book to track now and you don't want that.

var result = db.Books.AsNoTracking().SingleOrDefault(b => b.BookNumber == bookNumber);
Inenarrable answered 10/8, 2017 at 15:25 Comment(0)
A
1

Try It....

UpdateModel(book);

var book = new Model.Book
{
    BookNumber =  _book.BookNumber,
    BookName = _book.BookName,
    BookTitle = _book.BookTitle,
};
using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        try
        {
            UpdateModel(book);
            db.Books.Attach(book);
            db.Entry(book).State = EntityState.Modified;
            db.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}
Auxiliary answered 7/12, 2017 at 9:17 Comment(0)
H
1

I know it has been answered good few times already, but I like below way of doing this. I hope it will help someone.

//attach object (search for row)
TableName tn = _context.TableNames.Attach(new TableName { PK_COLUMN = YOUR_VALUE});
// set new value
tn.COLUMN_NAME_TO_UPDATE = NEW_COLUMN_VALUE;
// set column as modified
_context.Entry<TableName>(tn).Property(tnp => tnp.COLUMN_NAME_TO_UPDATE).IsModified = true;
// save change
_context.SaveChanges();
Hass answered 12/9, 2018 at 14:26 Comment(0)
H
0

I have the same problem when trying to update record using Attach() and then SaveChanges() combination, but I am using SQLite DB and its EF provider (the same code works in SQLServer DB without problem).

I found out, when your DB column has GUID (or UniqueIdentity) in SQLite and your model is nvarchar, SQLIte EF treats it as Binary(i.e., byte[]) by default. So when SQLite EF provider tries to convert GUID into the model (string in my case) it will fail as it will convert to byte[]. The fix is to tell the SQLite EF to treat GUID as TEXT (and therefore conversion is into strings, not byte[]) by defining "BinaryGUID=false;" in the connectionstring (or metadata, if you're using database first) like so:

  <connectionStrings>
    <add name="Entities" connectionString="metadata=res://savetyping...=System.Data.SQLite.EF6;provider connection string=&quot;data source=C:\...\db.sqlite3;Version=3;BinaryGUID=false;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>

Link to the solution that worked for me: How does the SQLite Entity Framework 6 provider handle Guids?

Hine answered 9/9, 2020 at 3:44 Comment(0)
J
0

Not related to this specific example, but I came across a challenge when trying to use EF and a DateTime field as the concurrency check field. It appears the EF concurrency code doesn't honor the precision setting from the metadata (edmx) i.e. Type="DateTime" Precision="3". The database datetime field will store a millisecond component within the field (i.e. 2020-10-18 15:49:02.123). Even if you set the original value of the Entity to a DateTime that includes the millisecond component, the SQL EF generates is this:

UPDATE [dbo].[People]
SET [dateUpdated] = @0
WHERE (([PeopleID] = @1) AND ([dateUpdated] = @2))
-- @0: '10/19/2020 1:07:00 AM' (Type = DateTime2)
-- @1: '3182' (Type = Int32)
-- @2: '10/19/2020 1:06:10 AM' (Type = DateTime2)

As you can see, @2 is a STRING representation without a millisecond component. This will cause your updates to fail.

Therefore, if you're going to use a DateTime field as a concurrency key, you must STRIP off the milliseconds/Ticks from the database field when retrieving the record and only pass/update the field with a similar stripped DateTime.

    //strip milliseconds due to EF concurrency handling
    PeopleModel p = db.people.Where(x => x.PeopleID = id);
    if (p.dateUpdated.Millisecond > 0)
    {
        DateTime d = new DateTime(p.dateUpdated.Ticks / 10000000 * 10000000);
        object[] b = {p.PeopleID, d};
        int upd = db.Database.ExecuteSqlCommand("Update People set dateUpdated=@p1 where peopleId=@p0", b);
        if (upd == 1)
            p.dateUpdated = d;
        else
            return InternalServerError(new Exception("Unable to update dateUpdated"));
    }
return Ok(p);

And when updating the field with a new value, strip the milliseconds also

(param)int id, PeopleModel person;
People tbl = db.People.Where(x => x.PeopleID == id).FirstOrDefault();
db.Entry(tbl).OriginalValues["dateUpdated"] = person.dateUpdated;
//strip milliseconds from dateUpdated since EF doesn't preserve them
tbl.dateUpdated = new DateTime(DateTime.Now.Ticks / 10000000 * 10000000);
Jitters answered 19/10, 2020 at 9:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.