2011-09-01 82 views
0

我试图使用实体框架如何加载嵌套的实体框架对象有效

类别,子类别和产品 以下类别代码到3深树装载到TreeView控件是一个IQueryable<ProductCategory>其中产品分类为一个EF4.0生成的对象(默认代码生成)

子类别是一个FK回类别表(所以在理论上,我们可以去任何深度,但数据域只会有两个级别)

var container = categories.Where(c=>c.somecondition).Include("Subcategories.Products"); 
foreach (var cat in container) { 
    addtoTree(cat); 
    foreach (var sub in cat.SubCategories) 
    { 
    addtoTree(sub); 
    foreach (var prod in sub.Products) addtoTree(prod); 

    } 
} 

这仍然针对每个内部循环迭代发出查询。我是否在EF配置中缺少某些东西(对上下文的更改?)以阻止这种情况的发生?或者还有另外一种写这种代码的方法吗?

(至于现在一个可怕的黑客,我已经创建了一个平展的信息的SQL视图,并且我认为迭代重新搭建手工嵌套的对象......讨厌,但是快!)

+0

发现额外的错误 - 如果你的代码(在我的情况下,在addtoTree(子安葬))试图引用备份的树,你需要包括在包含语句 - 即包括(“Subcategories.Products.Subcategories” )(在这种情况下,多对多的关系) – Andiih

回答

2

尝试通过在结束通话.ToList()循环之前急切地执行查询:

var container = categories 
    .Where(c => c.somecondition) 
    .Include("Subcategories.Products") 
    .ToList(); 
+0

我增加了ToList无济于事:我编辑的问题,更多的细节,该类别和子类别是相同的表...这可能是相关的(应该早点把原来) – Andiih

+0

实际上你的例子当然可以在我发布的简化例子上完美工作......我会试图找出真实世界中的实际例子! – Andiih

0

当与潜在的复杂层次处理,它可以帮助拉你需要的数据的简化结构。这样可以避免急于加载的需求,因为数据将被加入到结果中,加载所需内容,并且通常可以更好地利用数据库服务器端的索引。

例如,如果要加载的类,子类,并在树结构适合于显示器产品的“基本”的细节:

var results = dbContext.Categories.Where(c=> /*some condition*/) 
    .Select(c=> new {c.CategoryId, c.Name, SubCategories = 
     c.SubCategories.Select(sc=> new { sc.SubCategoryId, sc.Name, Products = sc.Products.Select(p=> new {p.ProductId, p.Name}) }) }).ToList(); 

当然,它可能看起来不漂亮,但没有魔法预先加载表达式的字符串以及EF生成的SQL通常会使用几个订单,效率更高&利用您通常希望在这些表上创建的索引。

对于简单的实体,您可以使用它来通过子层次结构选择向下,但是当处理较重的实体时,您只需要一些关键细节,这可以通过仅检索和传输来节省相当多的处理和网络带宽你需要的数据。