Entity Framework 5 - Update DbContext immediately after saving changes

I have an MVC application that uses Entity Framework 5. In several places, I have code that creates or updates entities, and then needs to perform some operations on the updated data. Some of these operations require access to the navigation properties, and I cannot update them.

Here is an example (simplified code that I have)

Models

class User : Model { public Guid Id { get; set; } public string Name { get; set; } } class Car : Model { public Guid Id { get; set; } public Guid DriverId { get; set; } public virtual User Driver { get; set; } [NotMapped] public string DriverName { get { return this.Driver.Name; } } } 

controller

 public CarController { public Create() { return this.View(); } [HttpPost] public Create(Car car) { if (this.ModelState.IsValid) { this.Context.Cars.Create(booking); this.Context.SaveChanges(); // here I need to access some of the resolved nav properties var test = booking.DriverName; } // error handling (I'm removing it in the example as it not important) } } 

The above example is for the Create method, but I also have the same problem with the Update method, which is very similar in that it simply takes an object from the context into the GET action and saves it using the Update method in the POST action.

 public virtual void Create(TObject obj) { return this.DbSet.Add(obj); } public virtual void Update(TObject obj) { var currentEntry = this.DbSet.Find(obj.Id); this.Context.Entry(currentEntry).CurrentValues.SetValues(obj); currentEntry.LastModifiedDate = DateTime.Now; } 

Now I tried several different approaches that I searched or found on the stack, but nothing works for me.

In my last attempt, I tried to unload the reboot after calling the SaveChanges method and requesting data from the database. Here is what I did.

I overlaid the SaveChanges method to update the context of the object immediately after saving

 public int SaveChanges() { var rowsNumber = this.Context.SaveChanges(); var objectContext = ((IObjectContextAdapter)this.Context).ObjectContext; objectContext.Refresh(RefreshMode.StoreWins, this.Context.Bookings); return rowsNumber; } 

I tried to get updated object data by adding this line of code right after calling SaveChanges in my HTTP Create and Update actions:

 car = this.Context.Cars.Find(car.Id); 

Unfortunately, the navigation property is still null . How can I correctly update the DbContext immediately after changing the data?

EDIT

I forgot to mention initially that I know a workaround, but it's ugly and I don't like it. Whenever I use the navigation property, I can check if it is null , and if that is, I can manually create a new DbContext and update the data. But I would really like to avoid such hacks.

 class Car : Model { [NotMapped] public string DriverName { get { if (this.Driver == null) { using (var context = new DbContext()) { this.Driver = this.context.Users.Find(this.DriverId); } } return this.Driver.Name; } } } 
+6
source share
2 answers

The problem is probably due to the fact that the element being added to the context is not a proxy with all the necessary components for lazy loading. Even after calling SaveChanges() element will not be converted to a proxy server.

I suggest you try using the DbSet.Create () method and copy all the values ​​from the entity that you get through the wire:

 public virtual TObject Create(TObject obj) { var newEntry = this.DbSet.Create(); this.Context.Entry(newEntry).CurrentValues.SetValues(obj); return newEntry; } 

UPDATE

If SetValues() poses a problem, I suggest you try automapper to transfer data from the passed object to the created proxy before Add with a new proxy instance in DbSet . Something like that:

 private bool mapCreated = false; public virtual TObject Create(TObject obj) { var newEntry = this.DbSet.Create(); if (!mapCreated) { Mapper.CreateMap(obj.GetType(), newEntry.GetType()); mapCreated = true; } newEntry = Mapper.Map(obj, newEntry); this.DbSet.Add(newEntry; return newEntry; } 
+4
source

I am using the following workaround: detach the object and load again

 public T Reload<T>(T entity) where T : class, IEntityId { ((IObjectContextAdapter)_dbContext).ObjectContext.Detach(entity); return _dbContext.Set<T>().FirstOrDefault(x => x.Id == entity.Id); } 
0
source

Source: https://habr.com/ru/post/948774/


All Articles