【问题标题】:Entity Framework Code First Circular dependencies实体框架代码优先循环依赖
【发布时间】:2013-10-15 00:01:57
【问题描述】:

我对 EF 的循环依赖有点困惑,因为它似乎一切都会变成循环依赖。

看着this tutorial

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }

    public virtual List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

当我在 Vs2012 中运行“代码映射”时,我确实看到它是一个循环引用

我不应该担心这个吗?我试图使用 Autofixture 生成虚拟数据,但由于循环引用而崩溃。

【问题讨论】:

    标签: c# entity-framework ef-code-first circular-dependency


    【解决方案1】:

    我想这取决于你问谁你是否应该担心双向关联。在领域驱动设计中,人们通常会说你应该担心这一点。 例如。 Eric Evans 在他的书Domain driven design: tackling the complexity in the heart of software 中说,如果可能,您应该避免使用它们。

    Julie Lerman 在最近的一篇帖子中写到了这个问题 here

    在您提供的实体框架的简单示例中,如果您删除了 Post 上的 Blog 和 BlogId 属性,应该不会有任何抱怨,但可能还有其他更复杂的情况。

    默认情况下,实体将在数据库的 Posts 行中将外键添加到拥有的 Blogs 行,但域模型只能从 Blogs 导航到 Posts。

    下面的sn-p会先从数据库中加载第一个Blog,然后懒加载那个博客的Posts。

    using (var db = new BlogContext())
    {
        var blog = db.Blogs.FirstOrDefault();
    
        //lazy loading the Posts of the blog that was fetched in previous line        
        foreach (var post in blog.Posts)
        {
            Trace.TraceInformation(string.Format("Title of post {0} is {1}",  post.Id, post.Title));
            }
        }
    }
    

    如果您真的需要从博客导航到帖子以及从帖子导航到博客,因为您的应用程序中有一些业务需求,那么您将不得不在查询和双向关联之间做出决定。 选择哪一个完全取决于您,Entity Framework 支持两者。

    双向关联是指您在两侧都有一个导航属性,使您能够在两个方向上导航。 IE。如果 Blog 有一个 Posts 属性并且每个 Post 都有一个指向 Blog 的 Blog 属性,那么我们就有了一个双向关联。

    另一种选择是仅在一侧具有导航属性。例如。一个博客可能包含一个帖子列表,这可以很容易地从博客导航到帖子,这可能是最需要的。 如果您在某些用例中引用了一篇文章并且需要找出它属于哪个博客,那么您可以通过在您的存储库/dbcontext 上进行查询来搜索在其列表中包含该文章的博客对象来找到该博客帖子数。

    DDD 的拥护者通常建议单向导航,如果需要反向导航,则进行查询。

    【讨论】:

    • 但是我失去了两个文件之间的链接并且基本上杀死了延迟加载(甚至急切加载),因为我不能再做 Post.Blog.Id,我将不得不编写一个单独的查询来做现在同样的事情。这不是限制EF吗?我对 EF 很陌生,我知道在 Nhibernate 中你必须在 Post 中有博客,否则链接永远不会发生。似乎 ORM 在某种程度上强制了这一点,即使我让它在数据库端没有循环引用,它也会存在于域中。
    • 没有双向导航就没有延迟加载。在上面的帖子中添加了示例代码。
    • 是的,我说的是从帖子到博客,而不是从博客到帖子。我只是习惯于访问域中的另一端,就像我说的那样,这对于 Nhibernate 来说几乎是强制性的。从你所说的EF不是强制性的,但我还没有尝试过。 “...查询和双向关联”是什么意思。
    • 添加了有关查询和双向关联的详细信息
    • 嗯,如果这个产品有很多有语言的产品标签,怎么样。现在我需要用语言找到 ProductA 的标签。我不知道如何通过链接在 DDD 中执行此操作,我认为这会很好。 var d = context.Products.Where(x => x.Id == new Guid()).First(); var found = d.ProductLabels.Where(x => x.Language.Code == "En").First();
    猜你喜欢
    • 1970-01-01
    • 2014-06-01
    • 2011-10-22
    • 2012-10-26
    • 2017-09-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多