Home > Mobile >  What is the best way to iterate through a C# object so only the modified fields are updated?
What is the best way to iterate through a C# object so only the modified fields are updated?

Time:09-16

Please excuse my limited knowledge of Entity Framework/C#. I'm sure there is an easy way to do what I wish to do.

I want to iterate through an object that I received from the database in order to check which fields are different from my update DTO. I wish to do this so only the changed fields are updated in the objFromDb. I am aware that if I only change the fields in the objFromDb that are modified, EF will only update the changed fields. I'm not sure if this is necessary or if there is a better way to do it.

Here is my update code (works but not the way I want it to) with the individual properties as well as the commented code that I was trying to accomplish. I don't like hard-coding the individual properties as this will require maintenance in the event that the object is changed.

    public T_IFS_EmployeeDTO Update(T_IFS_EmployeeDTO ojbDTO)
    {
        var objFromDb = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == ojbDTO.EmployeeID);

        if (objFromDb != null)
        {
            //foreach (var prop in objFromDb.GetType().GetProperties(BindingFlags.Instance))
            //{
            //    if (prop.GetValue(objFromDb) != prop.GetValue(ojbDTO))
            //    {
            //        objFromDb.prop.GetValue(objFromDb) = prop.GetValue(ojbDTO);
            //    }
            //}
            if (objFromDb.FirstName != ojbDTO.FirstName) objFromDb.FirstName = ojbDTO.FirstName;
            if (objFromDb.LastName != ojbDTO.LastName) objFromDb.LastName = ojbDTO.LastName;
            if (objFromDb.UserName != ojbDTO.UserName) objFromDb.UserName = ojbDTO.UserName;
            if (objFromDb.Password != ojbDTO.Password) objFromDb.Password = ojbDTO.Password;
            if (objFromDb.AccessLevel != ojbDTO.AccessLevel) objFromDb.AccessLevel = ojbDTO.AccessLevel;
            _db.T_IFS_Employee.Update(objFromDb);
            _db.SaveChanges();
            return _mapper.Map<T_IFS_Employee, T_IFS_EmployeeDTO>(objFromDb);
        }
        return ojbDTO;

I'm sure there is an easy way to do this but I haven't been able to figure it out. I do appreciate your time.

-Edit-

I think the following will work but will EF know if a field has not been modified and is it possible that it is as simple as this:

       var objFromDb = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == ojbDTO.EmployeeID);
       var objFromCall = _mapper.Map<T_IFS_EmployeeDTO, T_IFS_Employee>(ojbDTO);

        if (objFromDb != null)
        {
            objFromDb = objFromCall;

CodePudding user response:

Entity Framework Core will check the values of your entity and check them against a snapshot of what they were like when you loaded them. See this for the details.

So you should be able to do:

var objFromDb = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == ojbDTO.EmployeeID);
if (objFromDb != null)
{
    _mapper.Map<T_IFS_EmployeeDTO, T_IFS_Employee>(ojbDTO, objFromDb);
    //This overload of .Map sets properties in an existing object, as 
    //opposed to creating a new one
}

This will overwrite all properties in objFromDb with values from objDTO, But only the ones that are different will be written to the database when you call SaveChanges().

Setting objFromDb to objFromCall will overwrite your reference from the database and this won't be tracked at all.

And there's no need to call .Update() if you received the object from the DbContext and you haven't disabled change tracking.

  • Related