Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Refresh DbContext

I want to refresh all entities of my DbContext without recreating it, I tried the following and none of them make sense:

var context = ((IObjectContextAdapter)myDbContext).ObjectContext;

var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(
                                   EntityState.Added
                                   | EntityState.Deleted
                                   | EntityState.Modified
                                   | EntityState.Unchanged)
                          where entry.EntityKey != null
                          select entry.Entity);

context.Refresh(RefreshMode.StoreWins, refreshableObjects);
//.......................................................................
foreach (var entry in this.Orm.ChangeTracker.Entries())
{
    entry.State = EntityState.Unchanged;
}
this.Orm.ChangeTracker.DetectChanges();

And the only one which refreshes my DbContext:

foreach (var i in this.Orm.ChangeTracker.Entries())
    i.Reload();

But it's too slow. Can you help me choosing the right way?

like image 651
Mohsen Avatar asked Aug 11 '13 08:08

Mohsen


People also ask

How do you refresh entities?

To refresh an entity definition: Right-click the Entities folder and select Refresh Entity.

How do you refresh an object in C#?

//Get the object Product someProduct = someObjectContext. Product. First(); //At runtime at some point, recreate the ObjectContext someObjectContext = new SomeObjectContext(); //Try to refresh someProduct on the new ObjectContext someObjectContext. Refresh(RefreshMode.

How does DbContext change state of entity?

This can be achieved in several ways: setting the EntityState for the entity explicitly; using the DbContext. Update method (which is new in EF Core); using the DbContext. Attach method and then "walking the object graph" to set the state of individual properties within the graph explicitly.


3 Answers

I just found that the Enumerable result should be evaluated because the Refresh method gets it as object and doesn't evaluate it.

var context = ((IObjectContextAdapter)myDbContext).ObjectContext; var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(                                            EntityState.Added                                            | EntityState.Deleted                                            | EntityState.Modified                                            | EntityState.Unchanged)                           where entry.EntityKey != null                           select entry.Entity).ToList();  context.Refresh(RefreshMode.StoreWins, refreshableObjects); 

And I prefer the following:

var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList(); context.Refresh(RefreshMode.StoreWins, refreshableObjects); 
like image 150
Mohsen Avatar answered Oct 17 '22 23:10

Mohsen


I checked this and id works fine:

//Search
Box box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45);

//breakpoint here, change Name of Box by sql management studio

//Refresh
var context = ((IObjectContextAdapter)dbContext).ObjectContext;
context.Refresh(System.Data.Entity.Core.Objects.RefreshMode.StoreWins, box);

//Check refresh and if it is in context
box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45);

Are you sure it is the same db-context?

like image 43
yonexbat Avatar answered Oct 17 '22 23:10

yonexbat


In some cases, if a collection has been updated by a third party app, the collection may not be reloaded when refreshing the collection's object.

I had the case where I had an object A with a one to many relashionship to an object B.

Application 1 loads an object A with A.ListB empty. Application 2 fills the A.ListB collection. Application 1 reloads the object A.

With the solution above, A.ListB remains empty. I had to reload the collection A.ListB explicitly.

Here is a generic way to have all collections reloaded:

var context = ((IObjectContextAdapter)this).ObjectContext;

// detach all added entities
ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList().ForEach(e => e.State = EntityState.Detached);

// select entities
var refreshableObjects = ChangeTracker.Entries().Select(e => e.Entity).ToList();

// refresh each refreshable object
foreach (var @object in refreshableObjects)
{
    // refresh each collection of the object
    context.ObjectStateManager.GetRelationshipManager(@object).GetAllRelatedEnds().Where( r => r.IsLoaded).ToList().ForEach( c => c.Load() );

    // refresh the object
    context.Refresh(RefreshMode.StoreWins, @object);
}
like image 31
Anthony Brenelière Avatar answered Oct 17 '22 21:10

Anthony Brenelière