在实体框架4.1中同步反向关联的指导4.1 [英] Guidance for synchronising reverse associations in Entity Framework 4.1

查看:129
本文介绍了在实体框架4.1中同步反向关联的指导4.1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您创建实例时,EF 4.1会同步反向关联。有没有关于这种行为的文件或最佳实践指南?



我反对关联同步的意思是:

  public class Blog 
{
public Blog(){Posts = new List< Blog>(); }
public int Id {get;组; }
public ICollection< Post>帖子{get;私人集合
}

public class Post
{
public Blog Blog {get;组; }
public int Id {get;组; }
}

然后在以下行后,Post将其Blog属性设置为

  var blog = new Blog(); 
context.Blogs.Add(blog);
blog.Posts.Add(new Post());


解决方案

我相信 - 但我不知道 - 同步反向关联是指实体框架中的一个功能,称为关系修正关系跨度,并且负责在ObjectContext中的对象之间自动分配导航属性。这不是特定于EF 4.1,但也适用于较旧的版本。



我不知道此功能的全面文档,但这里有一些资源可能会给出更多的洞察力 - 特别是第二个:





修改



我无法全面解释关系跨度及其影响。但是我可以尝试给出一些例子,我感到安全,这并不完全是错误的:



答案您在评论中已链接 Morteza在派生自 EntityObject (只有 ObjectContext ,不可能在EF 4.1中使用 DbContext )和POCO(可能与 ObjectContext DbContext )。



如果您有POCO然后将新对象添加到已经加载到上下文中的另一个对象的导航集合中,将将新对象附加到上下文中。这并不奇怪,因为POCO是...,POCO,这意味着他们不了解EF环境。将一个对象添加到导航集合中,实际上并不仅仅是像 List< T> .Add(...)。这个通用的添加方法在EF上下文中不执行任何操作。



这是另一种情况, EntityObject EntityCollection ,它们都内部引用了上下文,因此可以在添加到集合中时立即附加到上下文中。



从这个考虑的一个结论是,你的问题的最后一个代码示例将实际设置 Blog <当您使用POCO时,code> Post 中的code>属性。但是,您调用 DetectChanges SaveChanges (调用 DetectChanges 内部)。在这种情况下, DetectChanges (这可能是一个非常复杂的方法)查看上下文中有什么对象(它会找到 Blog 父对象),然后遍历整个对象图(在我们的例子中为 Posts collection),并检查图中的其他对象( Post objects)也在上下文中。如果没有 - 在你的例子中就是这种情况 - 它会将它们附加到中的上下文中添加状态和 - 这里将关系跨度现在 - 还可以修正对象图形中的导航属性。



另外,关系跨度也与POCO相关联的情况是将对象加载到上下文中时。



例如:如果您有一个博客,其中id = x和 Post id = y,属于这个博客在数据库中,然后这个代码...

  var blog = context.Blogs.Find(x); //不需要加载帖子收藏! 
var post = context.Posts.Find(y); //不需要加载Blog属性!

将自动构建每个对象的导航属性,因此 / code> 的集合将突然包含博客属性在 Post 将引用博客。这种关系修复取决于事物确实加载到上下文中。如果您通过使用 AsNoTracking 来抑制此情况,例如...

  var blog = context.Blogs.AsNoTracking()。Where(b => b.Id == x).Single(); 
var post = context.Posts.AsNoTracking()。其中​​(p => p.Id == y).Single();

...关系跨度不起作用,导航属性将保持 null



最后一个注释:关系跨度 - 如上例所示 - 仅在至少一端的关联具有基数的 0 ... 1 (一对一或一对多关联)。它从来不适用于多对多协会。这是最近在这里讨论的(与EF 4.1): EF 4.1加载过滤的子集合不适用于多对多


EF 4.1 synchronises reverse associations when you create your instances. Is there any documentation of or best practices guidance available for this behaviour?

What I mean by synchronising the reverse association is that given:

public class Blog
{
   public Blog() { Posts = new List<Blog>(); }
   public int Id { get; set; }
   public ICollection<Post> Posts { get; private set; }
}

public class Post
{
   public Blog Blog { get; set; }
   public int Id { get; set; }
}

Then after the following line the Post will have it's Blog property set.

var blog = new Blog();
context.Blogs.Add(blog);
blog.Posts.Add(new Post());

解决方案

I believe - but I'm not sure - with "synchronising the reverse association" you mean a feature in Entity Framework which is called Relationship Fix-up or Relationship Span and is responsible to assign automatically navigation properties between objects in the ObjectContext. This is not specific to EF 4.1 but exists also for older versions.

I don't know a comprehensive documentation for this feature but here are a few resources which may give a bit more insight - especially the second one:

Edit

I am not able to give a comprehensive explanation of relationship span and all its impacts. But I can try to give a few examples where I feel safe that it's not completely wrong what I say:

In the answer you have linked in the comment Morteza makes a difference between entities which are derived from EntityObject (only ObjectContext in EF 4.0, not possible with DbContext in EF 4.1) and POCOs (possible with ObjectContext and DbContext).

If you have POCOs then adding a new object to a navigation collection of another object which is already loaded into the context would not attach the new object to the context. This is not surprising because POCOs are, well..., POCOs, which means that they don't know anything about the EF context. Adding an object to a navigation collection is really nothing more than something like List<T>.Add(...). This generic Add method doesn't do any operation on the EF context.

This is another situation with EntityObject and EntityCollection which both have references to the context internally and can therefore attach to the context immediately when you add to the collection.

One conclusion from this consideration is that the last code example in your question would not actually set the Blog property in the Post when you use POCOs. But: It will be set after you have called DetectChanges or SaveChanges (which calls DetectChanges internally). In this situation DetectChanges (which is probably a very complex method) looks into context what objects are there (it'll find the Blog parent object) and then runs through the whole object graph (the Posts collection in our case) and checks if the other objects in the graph (the Post objects) are also in the context. If not - and this is the case in your example - it will attach them to the context in Added state and - here comes relationship span into play now - also fix the navigation properties in the object graph.

Another situation where relationship span also acts with POCOs is when you load objects into the context.

For example: If you have a Blog with id = x and a Post with id = y which belongs to this Blog in the database then this code ...

var blog = context.Blogs.Find(x); // no eager loading of the Posts collection!
var post = context.Posts.Find(y); // no eager loading of the Blog property!

would automatically build up the navigation properties in each object, so the Posts collection of the Blog will suddenly contain the post and the Blog property in Post will refer to the blog. This relationship fix-up depends on the fact that the objects are indeed loaded into the context. If you suppress this by using AsNoTracking for example ...

var blog = context.Blogs.AsNoTracking().Where(b => b.Id == x).Single();
var post = context.Posts.AsNoTracking().Where(p => p.Id == y).Single();

... relationship span doesn't work and the navigation properties will stay null.

A last note: Relationship span - as in the example above - only works if the assocation on at least one end has a cardinality of 0...1 (one-to-one or one-to-many associations). It never works for many-to-many associations. This was recently discussed here (with EF 4.1): EF 4.1 loading filtered child collections not working for many-to-many

这篇关于在实体框架4.1中同步反向关联的指导4.1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆