重新加载实体和所有导航属性关联 - DbSet实体框架

时间:2012-01-31 14:32:06

标签: c# entity-framework ado.net entity-framework-4.1

我有实体关联刷新问题。当我得到这样的实体时:

MyContext context = new MyContext();

Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
Address myPersonAddress = myPerson.Address;

我找到了一个名为Address的关联和名为Name的属性的人。如果我手动修改数据库中的数据,例如属性Name,我必须使用以下代码重新加载我的实体:

context.Entry(myPerson).Reload();

我有Name的新值。但是,如果我为地址做同样的事情,它就不起作用。我认为这是因为地址是一个协会财产。我需要刷新它。

如何强制重新加载Address关联(以及Person类中的所有其他关联)?

编辑:

在同一案例中,一个人可以拥有多个地址。

MyContext context = new MyContext();

Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
List<Address> myPersonAddresses = myPerson.Addresses;

在这种情况下,它不是参考:

context.Entry(myPerson).Reference(p => p.Address).Load();
// Address will be populated with only the new address
// this isn't required because I use lazy loading

但是收藏:

context.Entry(myPerson).Collection(p => p.Addresses).Load();
// Address will be populated with old value and new value

我需要用它来工作:

context.Entry(myPerson).Collection(p => p.Addresses).CurrentValue.Clear();
context.Entry(myPerson).Collection(p => p.Addresses).Load();

但对于我的所有导航属性来说,它似乎不是一个很好的解决方案!

4 个答案:

答案 0 :(得分:28)

如果您不使用延迟加载,则可以显式加载新的Address(因为您必须显式加载它(例如,使用Include),当您加载{{ 1}}最初):

Person

如果使用延迟加载,则不需要第二个代码块。尽管如此,只要您访问新context.Entry(myPerson).Reload(); // If the person refers to another Address in the DB // myPerson.Address will be null now if (myPerson.Address == null) context.Entry(myPerson).Reference(p => p.Address).Load(); // myPerson.Address will be populated with the new Address now 的属性(就像上面第二个代码块中有新查询一样),就会获得对数据库的新查询,因为第一行会将导航属性标记为未加载如果此人引用了数据库中的新地址。

此行为不取决于您是否在模型类中公开了外键。

似乎没有办法调用一个单一的魔术myPerson.Address方法,它会在一次调用中重新加载和更新整个对象图(类似于没有单个Reload来加载一个完整的对象图)。

答案 1 :(得分:7)

谢谢!

context.Entry(myPerson).Collection(p => p.Addresses).Load();

为我做了工作。

如果p.Addresses丢失了一个条目,则可以通过

刷新
((IObjectContextAdapter)CurrentContext(context)).ObjectContext.Refresh(RefreshMode.StoreWins, p.Addresses);

但是如果它获得了一个条目,只有你的.Load()方法有帮助。再次感谢!

答案 2 :(得分:2)

您需要使用Query()扩展名来修改LINQ表达式。这是一个基于我的personcal代码的例子。在这段代码中,我重新加载了具有myPerson对象的相关AddressType导航属性的Addresses集合,并将结果放入SomeList:

_DbContext.Entry<Person>(myPerson)
          .Collection(i => i.Adresses) // navigation property for Person
          .Query()
          .Include("AddressType")        // navigation property for Address
          .OrderBy(i => i.Name)
          .ThenBy(i => i.AddressType.AddressTypeName) // just an example
          .Select(i => new someClass
          {
              SoomeField1 = i.SomeField1,
              ...
          })
          .ToList()
          .ForEach(i => SomeList.Add(i)); // SomeList is a List<T>

答案 3 :(得分:-2)

我在从dbContext读取对象之前使用Detach解决了这个问题。 此方法允许我刷新对象的所有导航属性。 我在这里描述了我的场景和解决方案的细节 Entity Framework: Reload newly created object / Reload navigation properties