重新加载实体和所有导航属性关联-DbSet实体框架
本文关键字:实体 导航 属性 关联 框架 -DbSet 新加载 加载 | 更新日期: 2023-09-27 18:21:55
我在实体关联刷新方面遇到问题。当我得到一个这样的实体:
MyContext context = new MyContext();
Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
Address myPersonAddress = myPerson.Address;
我找了一个人,他有一个名为Address的关联,还有一个名叫Name的房产。如果我手动修改数据库中的数据,例如属性名称,我必须使用以下代码来重新加载我的实体:
context.Entry(myPerson).Reload();
我有了Name的新值。但如果我对Address也这样做,那就行不通了。我认为这是因为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();
但对于我的所有导航属性来说,这样做似乎不是一个好的解决方案!
如果不使用延迟加载,则必须显式加载新的Address
(因为在最初加载Person
时,必须显式地加载它(例如,使用Include
)):
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
方法,该方法可以在一次调用中重新加载和更新整个对象图(类似于没有一个Include
来急于加载一个完整的对象图)。
如果它获得了一个条目,那么只有.Load()方法有帮助。
context.Entry(myPerson).Collection(p => p.Addresses).Load();
如果p.地址丢失了一个条目,则可以由刷新
((IObjectContextAdapter)CurrentContext(context)).ObjectContext.Refresh(RefreshMode.StoreWins, p.Addresses);
您需要使用Query()扩展来修改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>
在从dbContext读取对象之前,我已经使用Detach解决了这个问题。此方法允许我刷新对象的所有导航属性。我在这里描述了我的场景和解决方案的细节实体框架:重新加载新创建的对象/重新加载导航属性