Hello. I have a table that I pull using EF from the database and pass to the ViewModel for editing (edit window). View displays a DataGrid, where binding is carried out to entity fields. Below View (edit window) 2 Save and Exit buttons. When you click on Save, I call the Update command and the local data is saved in the database. When you click on the exit, just close the window.

When you reopen the window, I do a Get command, but the data is taken not from the database but from the local storage. Those. changed data. Can I somehow undo all local changes?

If by example, the whole problem is described as:

//station.Name был равен Name1 var station= _unitOfWork.StationRepository.Get().First(); //поменяли в локальной коллекции без Update в БД station.Name = "NEWname"; //сделали запрос чтобы к БД (хочу предыдущее состояние) station = _unitOfWork.StationRepository.Get().First(); // но station.Name уже "NEWname"; 

Tell me how best to edit data from the database?

repository code

 public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class { protected CisDbContext Context { get; } protected DbSet<TEntity> DbSet { get; } public GenericRepository(CisDbContext context) { Context = context; DbSet = context.Set<TEntity>(); } public virtual IQueryable<TEntity> Get() { return DbSet; } } 

Screenshot of the changes made in the nested table (many to many). The UndoChanges method does not remove them.

enter image description here

    2 answers 2

    To prevent data from being placed in the cache, the AsNoTracking() method is used. When it is applied, the data returned from the request is not cached.

     var station = _unitOfWork.StationRepository.Get().AsNoTracking().FirstOrDefault(); 

    When the data context retrieves data from the database, the Entity Framework places the retrieved objects in the cache and tracks the changes that occur to these objects until the SaveChanges() method is used.

    Update

    If you want to save changes, use the Attach() method and change the state to Modified

     using (var context = new myContext()) { var station= context.Station.AsNoTracking().FirstOrDefault(); station.Name = "New_Name"; context.Station.Attach(station); context.Entry(station).State = System.Data.Entity.EntityState.Modified; context.SaveChanges(); } 
    • Thank!! on a simple example works. But in my sulchai, AsNoTracking () results in an exception, with the update command. Now I will write what exception. - Aldmi
    • swears at DbSet.Attach (entity); - Aldmi
    • This is not the same as the primary key value. This can be what happens when you see the graph of the question. The database generated key values. In this case, it should be noted that this is the case. - Aldmi
    • @Aldmi is duplicated with the primary key, apparently you are trying to add a new edited object whose id is the same as the previous one. - Murad
    • Yes, this occurs when using AsNoTracking. Without it, everything is fine. Is it possible to reset caching by calling SaveChanges () without using Update? - Aldmi

    Here is the code that undoes changes made after the last call to dbContext.SaveChanges ().

     public static void UndoChanges(this DbContext dbContext) { foreach (var entry in dbContext.ChangeTracker.Entries()) { switch (entry.State) { case EntityState.Modified: entry.State = EntityState.Unchanged; break; case EntityState.Deleted: entry.Reload(); break; case EntityState.Added: entry.State = EntityState.Detached; break; } } } 
    • Is this extension method for context? and should I call it manually when I want to undo the changes? - Aldmi
    • @Aldmi Yes, everything is correct. The code in the example corrected. - Murad
    • I'd rather put it in UnitOfWork than in a specific repository, since Are changes to the entire context canceled? - Aldmi
    • @Aldmi Well, this is up to you, it all depends on the logic of your code. I used to roll back changes with exceptions in SaveChanges (). - Murad
    • It works on the properties of the entity itself, and I choose the OperativeSchedule collection from the OperativeSchedule list from the OperativeSchedule ICollection <OperativeSchedule> collection of the nested entity, and the selected element remains. Maybe because I don't have an intermediate table in context? and he can't track changes? - Aldmi