【问题标题】:Eager load a self-referencing table急切加载自引用表
【发布时间】:2018-02-20 22:16:46
【问题描述】:

我有一个Categories 的标准自引用表。在我的实体模型中,我建立了关联 ChildrenParent。是否可以在不延迟加载的情况下加载整个 Category 对象?

如果我使用下面的代码,它只会加载到第二级。

db.Categories.MergeOption = System.Data.Objects.MergeOption.NoTracking;

var query = from c in db.Categories.Include("Children")
            where c.IsVisible == true
            orderby c.SortOrder, c.Id
            select c;

如果我已经加载了所有类别对象,是否可以加载引用?

加载它的一种方法是多次添加Children属性

db.Categories.Include("Children.Children.Children.Children.Children")

但这会生成一个很长的疯狂 T-SQL 代码,而且它也不能满足我的要求。

【问题讨论】:

    标签: c# entity-framework hierarchical-data


    【解决方案1】:

    不,这是不可能的。考虑:所有 LINQ to Entities 查询都被转换为 SQL。哪个 SQL 语句在自引用层次结构中包含无限深度?在标准 SQL 中,没有一个。如果在 T-SQL 中有对此的扩展,我不知道它是什么,我认为 EF 提供程序也不会这样做。

    【讨论】:

    • 但如果我运行查询“SELECT * FROM Categories”,我已经加载了整个表,并且我已经加载了所有父子类别,因为它们都在一个表中。那么在这种情况下,将这个加载的记录分配给引用的属性并不是很复杂?
    • 如果您实际上迭代了整个表,那么所有对象在内存中并且已经修复,无论是否包含Include。但这不会发生,直到您到达表中的最后一条记录。包含保证相关对象将出现在您迭代的 first 记录中。
    • "哪个 SQL 语句在自引用层次结构中包含无限深度?" -> T-SQL 中的常用表表达式
    • 他没有在一次查询中要求它。但根据下面的评论,我猜这就是他正在寻找的东西。
    【解决方案2】:

    好的,您可以考虑使用 Load 方法。

     if (!category.Children.IsLoaded)
            category.Children.Load();
    

    当然,类别实体需要被ObjectContext跟踪。

    这里有更好的解释how-does-entity-framework-work-with-recursive-hierarchies-include-seems-not-to

    【讨论】:

    • 我知道这种方法(它会生成数百个 T-SQL 查询),但我也必须在不跟踪的情况下加载它,因为我将它保存到缓存中。我正在寻找别的东西。如果我加载整个类别表,我还加载了父类和子类,但未加载关联属性。我也有 CategoryType 的相关表,我必须为每个类别加载它,无论它们引用同一行...
    • 好的,我没有看到你必须缓存它。嗯,我会试着想想如何解决这个问题。
    【解决方案3】:

    我用来实现的一种方法是,如果我有多个实体,我想在自引用表中获取所有子项是使用 recursive ctestored procedure 来使用 Entity FrameWork 获取他们的 ID: Here is the code using Entity Framework and code first approach

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-06
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 2017-09-15
      相关资源
      最近更新 更多