41

With EF4 CTP5 DbContext, what is the equivalent of this

    public void Refresh(Document instance)
    {
        _ctx.Refresh(RefreshMode.StoreWins, instance);
    }

I've tried this but it doesn't do the same thing, updating the instance

    public void Refresh(Document instance)
    {
        _ctx.ChangeTracker.DetectChanges();
    }

?

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
mare
  • 13,033
  • 24
  • 102
  • 191

3 Answers3

58

You must use this:

public void Refresh(Document instance)
{
  _ctx.Entry<Document>(instance).Reload();
}
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
26

The above doesn't work. Reload() method does not correctly refresh the entity from the database. It performs SQL select query but does not build proxies for the navigational properties. See the example below (I use the Northwind database in SQL Server with EF 5.1):

NorthwindEntities northwindEntities = new NorthwindEntities();
Product newProduct = new Product
{
    ProductName = "new product",
    Discontinued = false,
    CategoryID = 3
};
northwindEntities.Products.Add(newProduct);
northwindEntities.SaveChanges();

// Now the product is stored in the database. Let's print its category

Console.WriteLine(newProduct.Category); // prints "null" -> navigational property not loaded

// Find the product by primary key --> returns the same object (unmodified)
// Still prints "null" (due to caching and identity resolution)
var productByPK = northwindEntities.Products.Find(newProduct.ProductID);
Console.WriteLine(productByPK.Category); // null (due to caching)

// Reloading the entity from the database doesn't help!
northwindEntities.Entry<Product>(newProduct).Reload();
Console.WriteLine(newProduct.Category); // null (reload doesn't help)

// Detach the object from the context
((IObjectContextAdapter)northwindEntities).ObjectContext.Detach(newProduct);

// Now find the product by primary key (detached entities are not cached)
var detachedProductByPK = northwindEntities.Products.Find(newProduct.ProductID);
Console.WriteLine(detachedProductByPK.Category); // works (no caching)

I may conclude that real refresh / reload of EF entity can be done by Detach + Find:

((IObjectContextAdapter)context).ObjectContext.Detach(entity);
entity = context.<SomeEntitySet>.Find(entity.PrimaryKey);

Nakov

Svetlin Nakov
  • 1,599
  • 18
  • 19
  • 8
    From a NAA of @Dimitar-Dimitrov: `You use the constructor of your POCO class to create a new Product object and thus it will not be proxy. You should use the DbSet.Create method in order to get proxy. When you detach the entity from the context and load it from the database with the Find method, Entity Framework will create a proxy for the entity. That's why it works with Detach+Find. However, DbEntityEntry.Reload method will not refresh the relationships of the entity.` – bummi Nov 27 '13 at 15:22
  • 1
    @bummi Thanks for posting that quote. Using DbSet.Create instead of just "new " to initialize my entity allowed my navigation properties to work after saving changes and reloading the entity. – Brent Keller Aug 22 '14 at 14:14
  • Thank you very much. This works for me. Reload does not work for either when data has been modified outside of EF. – user1841243 Nov 24 '14 at 10:36
  • strange behaviour: after deleting and re-adding a child entity to a parent... my refreshed parent-entity has now 2 children instead of 1... The deleted child-entity is still there for some reason. – user1841243 Nov 24 '14 at 11:05
  • I tried the Create, Add, Save and Reload method and my variable still did not have my new entity's database Id. How the heck is this so difficult? – Andy Raddatz Aug 25 '15 at 19:50
-1

I found that the reload fails on proxy entities that have navigation properties.

As a work around, reset the current values and then reload like this:

var entry =_ctx.Entry<Document>(instance);
entry.CurrentValues.SetValues(entry.OriginalValues); 
entry.Reload();
Matstar
  • 402
  • 3
  • 6