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

C# 重新加载实体和所有导航属性关联-DbSet实体框架,c#,entity-framework,ado.net,entity-framework-4.1,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和property的名字。如果手动修改数据库中的数据(例如属性名称),则必须

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

MyContext context = new MyContext();

Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
Address myPersonAddress = myPerson.Address;
我得到了一个名为Address和property的名字。如果手动修改数据库中的数据(例如属性名称),则必须使用以下代码重新加载实体:

context.Entry(myPerson).Reload();
我的名字有了新的值。但如果我对地址做同样的操作,它就不起作用了。我认为这是因为地址是一个关联属性。我需要刷新一下

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

编辑:

在同一情况下,一个人可以有多个地址

MyContext context = new MyContext();

Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
List<Address> myPersonAddresses = myPerson.Addresses;
但是一个集合:

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();

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

如果您不使用延迟加载,则可以显式加载新的
地址
(例如,当您最初加载
人员
时,您必须显式加载它):

如果使用延迟加载,则不需要第二个代码块。尽管如此,只要访问新的
myPerson.Address
(就像上面第二个代码块中有一个新查询)的属性,您就会得到一个对数据库的新查询,因为如果此人引用数据库中的新地址,第一行会将导航属性标记为未加载

这种行为并不取决于您是否在模型类中公开了外键

似乎没有一种方法可以调用某个magic
Reload
方法,该方法可以在一次调用中重新加载和更新整个对象图(类似于没有单个
Include
来急于加载完整的对象图)。

您需要使用扩展来修改LINQ表达式。这里是一个基于我个人代码的示例。在这段代码中,我使用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>
\u DbContext.Entry(myPerson)
.Collection(i=>i.address)//个人的导航属性
.Query()
.Include(“AddressType”)//地址的导航属性
.OrderBy(i=>i.Name)
.ThenBy(i=>i.AddressType.AddressTypeName)//只是一个例子
.选择(i=>newsomeclass
{
SoomeField1=i.SomeField1,
...
})
托利斯先生()
.ForEach(i=>SomeList.Add(i));//SomeList是一个列表

我在从dbContext读取对象之前使用Detach解决了这个问题。 此方法允许我刷新对象的所有导航属性。 我已经在这里描述了我的场景和解决方案的细节

如果它获得一个条目,则只有.Load()方法有帮助

context.Entry(myPerson).Collection(p => p.Addresses).Load();
如果p.地址丢失了一个条目,可以通过

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

你的意思是
context.Entry(MyPersonalAddress).Reload()
不起作用吗?是的,这意味着不起作用。因为此方法只重新加载属性(=名称),而不加载关联(=地址)啊,对不起,我误解了。因此,您不希望重新加载同一
地址
实体的标量属性,而希望重新加载与另一
地址
实体的关系。嗯,问得好。
Person
是否有
地址
导航属性的公开外键属性?如何公开外键属性?你什么意思?我的.csdlI中有一个导航属性。我同意,似乎没有一种方法可以调用单个方法重载。不幸的是,类中并不是只有引用。你也可以收藏一些!(我编辑了我的问题以便涵盖所有案例)@Sam:我明白了。但我认为对于集合,逻辑是相同的(用
集合
替换
引用
)。不幸的是,您必须对每个导航属性分别执行此操作(就像您必须对每个导航属性使用
Include
以进行即时加载)。@Slauma
dbContext.Entry(test).Collection(x=>x.TestChildren.Load()未重新加载实体框架核心的集合。如果您有时间,请看一看:禁用惰性负载对我有效
context.Entry(myPerson).Collection(p => p.Addresses).Load();
((IObjectContextAdapter)CurrentContext(context)).ObjectContext.Refresh(RefreshMode.StoreWins, p.Addresses);