0

I want to have method to update only specified properties in my entity. So I created method as below:

public async Task UpdateAsync(string uri, Action<Models.RequestObject> modify, CancellationToken cancellationToken = default)
{
    Entities.RequestObject entity = _dbContext.RequestObjects.Local.SingleOrDefault(p => p.Uri == uri)
        ?? await _dbContext.RequestObjects.AsTracking().Where(p => p.Uri == uri).SingleOrDefaultAsync(cancellationToken);

    if (entity != default)
    {
        Models.RequestObject entityAsModel = entity.ToModel();
        modify.Invoke(entityAsModel);

        entity = entityAsModel.ToEntity();
        await _dbContext.SaveChangesAsync(cancellationToken);
    }
}

But this method, due to project architecture, accepts Models.RequestObject as Action generic type, but I need to modify Entities.RequestObject. The code I provided doesn't work. Any ideas why, and how to fix it?

Szyszka947
  • 473
  • 2
  • 5
  • 21

1 Answers1

2

The reason why it is not working, is because you are not updating the entity that is being tracked by the entity framework.

  • You first get the entity
  • Then you map it to a model
  • Then you update the model
  • Then you map the model back to an entity and reassign it to the entity variable

So now you have 2 entity objects in memory 1 that you fetched from the entity framework and one which you reated by calling .ToEntity()

If you change the code to modify the entity that you got back from the entity framework e.g.

public async Task UpdateAsync(string uri, Action<Models.RequestObject> modify, CancellationToken cancellationToken = default)
{
    Entities.RequestObject entity = _dbContext.RequestObjects.Local.SingleOrDefault(p => p.Uri == uri)
        ?? await _dbContext.RequestObjects.AsTracking().Where(p => p.Uri == uri).SingleOrDefaultAsync(cancellationToken);

    if (entity != default)
    {
        Models.RequestObject entityAsModel = entity.ToModel();
        modify.Invoke(entityAsModel);

        entity.prop1 = entityAsModel.prop1;
        entity.prop2 = entityAsModel.prop2;

        await _dbContext.SaveChangesAsync(cancellationToken);
    }
}

Then it will properly update the entity in the database.

Selmir Aljic
  • 268
  • 2
  • 9
  • Hm, but any ideas how to avoid manually setting up properties? – Szyszka947 Mar 21 '23 at 11:51
  • @Szyszka947 What I’ve done in the past is use `AutoMapper` `mapper.Map(source,destination)` but honestly there are a lot of different ways to avoid manually setting the properties, it can probably be a question on it’s own on stack overflow. It might’ve already been asked before. – Selmir Aljic Mar 21 '23 at 12:41
  • 1
    @Szyszka947 Here are some alternative ways for updating which might you might consider taking. https://stackoverflow.com/questions/15336248/entity-framework-5-updating-a-record?rq=1 – Selmir Aljic Mar 21 '23 at 12:58