简体   繁体   English

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

[英]Reload an entity and all Navigation Property Association- DbSet Entity Framework

I have a problem with entity association refresh.我有实体关联刷新的问题。 When I get an entity with like this:当我得到这样的实体时:

MyContext context = new MyContext();

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

I got an a person with an association named Address and a property named Name.我有一个人有一个名为 Address 的关联和一个名为 Name 的属性。 If I modify manually the datas in database for example the property Name, I have to use the following code to reload my entity:如果我手动修改数据库中的数据,例如属性名称,我必须使用以下代码重新加载我的实体:

context.Entry(myPerson).Reload();

and I have the new value for Name.我有名称的新值。 But If I do the same for Address it doesn't work.但是如果我对 Address 做同样的事情,它就行不通了。 I think it is because Address is an association property.我认为这是因为 Address 是一个关联属性。 I need to refresh it.我需要刷新它。

How Can I do to force the reload of Address association (and all other association in Person class) ?如何强制重新加载地址关联(以及 Person 类中的所有其他关联)?

EDIT:编辑:

In the same case, a person can have more than one address.在同一情况下,一个人可以有多个地址。

MyContext context = new MyContext();

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

In this case, it is not a Reference:在这种情况下,它不是参考:

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

but a Collection:但是一个集合:

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

I need to use this to work:我需要使用它来工作:

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

But it doesn't seem to be a good solution to do this for all my navigation properties!但是对于我的所有导航属性执行此操作似乎不是一个好的解决方案!

If you don't use lazy loading, you have the load the new Address explicitly (as you had to load it explicitly (with Include , for example), when you loaded the Person initially):如果您不使用延迟加载,则可以显式加载新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

If you use lazy loading, you don't need the second code block.如果使用延迟加载,则不需要第二个代码块。 Nonetheless, you get a new query to the database as soon as you access properties of the new myPerson.Address (like you have a new query in the second code block above) because the first line will mark the navigation property as not loaded if the person refers to a new address in the DB.尽管如此,只要您访问新的myPerson.Address属性(就像您在上面的第二个代码块中有一个新查询一样),您就会立即获得对数据库的新查询,因为第一行会将导航属性标记为未加载,如果person 指的是数据库中的新地址。

This behaviour doesn't depend on whether you have exposed the foreign key in the model class or not.此行为不取决于您是否已在模型类中公开外键。

There doesn't seem to be a way to call some single magic Reload method which would reload and update the whole object graph in one call (similar like there is no single Include to eager load a complete object graph).似乎没有一种方法可以调用某个单一的魔法Reload方法,该方法会在一次调用中重新加载和更新整个对象图(类似于没有单个Include来急切加载完整的对象图)。

If it gained one entry, only your .Load() method helped.如果它获得了一个条目,则只有您的 .Load() 方法有帮助。

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

If p.Addresses lost one entry, it can be refreshed by如果 p.Addresses 丢失了一个条目,可以通过

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

You need to use Query() extension to modify your LINQ expression.您需要使用Query()扩展来修改您的 LINQ 表达式。 Here it is an example on basis of my personcal code.这是基于我的个人代码的示例。 In this code I reload Addresses collection with related AddressType navigation property for myPerson object and place the result into SomeList:在此代码中,我使用 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>

I've solved this problem with using Detach before reading object from dbContext.我在从 dbContext 读取对象之前使用 Detach 解决了这个问题。 This method allowed me to refresh all navigation properties of the object.这个方法允许我刷新对象的所有导航属性。 I've described my scenario and details of solution here Entity Framework: Reload newly created object / Reload navigation properties我已经在实体框架中描述了我的场景和解决方案的详细信息:重新加载新创建的对象/重新加载导航属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM