7

What is the best way to update data in EF core in asp.net core application? I can do it like this

public class Repository<T> : IRepository<T> where T : BaseEntity
{
    private DbContext context;
    private DbSet<T> entities;
    public Repository(DbContext context)
    {
        this.context = context;
        this.entities = context.Set<T>();
    }
    public void Update(T entity)
    {
        T exist = this.entities.Find(entity.Id);
        this.context.Entry(exist).CurrentValues.SetValues(entity);  

        this.context.SaveChanges();
    }

}

Or i can use the Update() method of DbSet. But to use it I need to set QueryTrackingBehavior to "no-tracking" firstly, something like this:

public class Repository<T> : IRepository<T> where T : BaseEntity
{
    private DbContext context;
    private DbSet<T> entities;
    public Repository(DbContext context)
    {
        this.context = context;
        this.context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        this.entities = context.Set<T>();
    }
    public void Update(T entity)
    {
        this.entities.Update(entity); 

        this.context.SaveChanges();
    }

}

Is it a good idea? What option is better and why?

user3233682
  • 127
  • 1
  • 3
  • 9
  • 2
    Depends mainly on whether you work [connected or disconnected](https://learn.microsoft.com/en-us/ef/core/saving/disconnected-entities). In fact, the link gives you all the information you need to make your own decision. – Gert Arnold Jan 13 '19 at 14:27

1 Answers1

14

According to EF Core documentaion

SetValues will only mark as modified the properties that have different values to those in the tracked entity. This means that when the update is sent, only those columns that have actually changed will be updated. (And if nothing has changed, then no update will be sent at all.)

So I think your first approach (this.context.Entry(exist).CurrentValues.SetValues(entity);) should be the best for updating entity!

TanvirArjel
  • 30,049
  • 14
  • 78
  • 114
  • 1
    How do you know? What if they work connected? Your answer is premature. Also, when working disconnected there's [more to it](https://stackoverflow.com/a/30824229/861716). – Gert Arnold Jan 13 '19 at 15:04
  • 1
    @GertArnold as he is updating the entity, it is reasonable that he will make sure that the entity is being tracked! – TanvirArjel Jan 13 '19 at 15:05
  • 1
    Well, maybe they don't want the extra db roundtrip. Maybe the entity contains an entire object graph, good luck with setting all values. – Gert Arnold Jan 13 '19 at 15:10
  • `don't want the extra db roundtrip`-They how will he pull desired data from database for update. Whenever he will pull the data from database for the update EF/ EF Core started tracking the data. unless he mention `AsNoTracking()` explicitly. – TanvirArjel Jan 13 '19 at 15:13
  • 1
    Attach an entity and set it to `Modified`: no roundtrip. There are so many aspects to this question that it can't be answered by one correct answer. Therefore, it's off-topic here. – Gert Arnold Jan 13 '19 at 15:26
  • No attaching and Modified is needed in EF Core. You can just pull the data and change data then `SaveChanges()` will updated the data. Even no `_dbContext,Update(Entity)`; is needed! – TanvirArjel Jan 13 '19 at 15:29
  • Thank you. Another one question: why I need to set NoTracking explicitly? Without it Update() method throws an exception, that the entity with given key already tracked? what is wrong? i use one instance of Repository/Context per one request(adding DI as AddTransient) – user3233682 Jan 13 '19 at 16:26
  • 1
    Okay! Whenever you pull an entity from database EF Core started tracking it unless you call `AsNoTracking` in the query! So Whenever you again called `Update(entity)` manually that means you are trying to track an entity that is already being tracked! Clear? – TanvirArjel Jan 13 '19 at 16:53
  • @Tanvir as OP says its Asp.Net app which is disconnected application.Typically You get data from the browser, convert to disconnected entity. Now either you have to attach it (one call)or pull from DB and set the values and save (two calls) – LP13 Jun 07 '19 at 03:21
  • This is the only polymorphic answer I've found , although I don't like the extra round trip to the DB either . – LostNomad311 Aug 12 '19 at 19:50