创建实例时,EF 4.1会同步反向关联。是否有任何有关此行为的文档或最佳实践指南?

通过同步反向关联,我的意思是给定的:

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; }
}

然后,在下面的行之后,Post将设置为Blog属性。
var blog = new Blog();
context.Blogs.Add(blog);
blog.Posts.Add(new Post());

最佳答案

我相信-但我不确定-“同步反向关联”是指Entity Framework中的一项功能,称为 Relationship Fix-up Relationship Span ,它负责在对象中的对象之间自动分配导航属性。 ObjectContext。这不是特定于EF 4.1,但对于较旧的版本也存在。

我不知道有关此功能的全面文档,但是这里有一些资源可能会提供更多的见解-尤其是第二篇:

  • 简要定义:http://blogs.msdn.com/b/alexj/archive/2009/04/03/tip-10-understanding-entity-framework-jargon.aspx
  • 更详细的解释(Zeeshan Hirani):http://www.daltinkurt.com/upload/dosyalar/file/Diger/entity_framework_learning_guide.pdf(第125-133页的第3.4章)
  • 关于想要避免关系跨度的情况:http://blogs.msdn.com/b/alexj/archive/2009/04/07/tip-11-avoiding-relationship-span.aspx

  • 编辑

    我无法全面解释关系范围及其所有影响。但是我可以尝试举几个例子,让我感到放心,这并不是我所说的完全错误:

    answer you have linked in the comment中,Morteza区分了从EntityObject(在EF 4.0中仅ObjectContext,在EF 4.1中的DbContext无法实现)和POCO(可能在ObjectContextDbContext中)派生的实体之间。

    如果您有POCO,则将新对象添加到已加载到上下文中的另一个对象的导航集合中,将不会将新对象附加到上下文。这并不奇怪,因为POCO是POCO,这意味着它们对EF上下文一无所知。实际上,将对象添加到导航集合只不过是List<T>.Add(...)之类的东西。这个通用的Add方法在EF上下文上不执行任何操作。

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

    从这一考虑得出的结论是,当您使用POCO时,问题中的最后一个代码示例实际上不会在Blog中设置Post属性。但是:将在您调用DetectChangesSaveChanges(内部调用DetectChanges)之后进行设置。在这种情况下,DetectChanges(这可能是一种非常复杂的方法)会根据上下文查看存在的对象(它将找到Blog父对象),然后遍历整个对象图(在我们的示例中为Posts集合),并检查是否存在图中的其他对象(Post对象)也位于上下文中。如果不是(在您的示例中就是这种情况),它将以Added状态将它们附加到上下文,并且-现在关系跨度开始发挥作用-还修复了对象图中的导航属性。

    关系跨度也与POCO一起起作用的另一种情况是将对象加载到上下文中时。

    例如:如果您有一个id = x的Blog和一个id = y的Post,它们在数据库中属于此Blog,则此代码...
    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!
    

    会自动在每个对象中建立导航属性,因此PostsBlog集合将突然包含该帖子,并且Blog中的Post属性将引用博客。这种关系修复取决于以下事实:对象确实已加载到上下文中。例如,如果通过使用AsNoTracking来抑制此问题,则...
    var blog = context.Blogs.AsNoTracking().Where(b => b.Id == x).Single();
    var post = context.Posts.AsNoTracking().Where(p => p.Id == y).Single();
    

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

    最后要注意的是:关系跨度(如上面的示例中所示)仅在至少一端的关联具有0...1(一对一或一对多关联)的基数时才有效。它对多对多协会永远都行不通。最近在这里(使用EF 4.1)对此进行了讨论:EF 4.1 loading filtered child collections not working for many-to-many

    关于entity-framework-4.1 - Entity Framework 4.1中同步反向关联的指南,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6251914/

    10-14 12:19