使用Linq to SQL,我如何Eager加载所有子项和任何嵌套子项结果

Bre*_*uck 5 c# asp.net linq-to-sql

我在L2S Classes dbml中有5个表:Global >> Categories >> ItemType >> Item >> ItemData.对于下面的例子,我只去了itemtype.

    //cdc is my datacontext

DataLoadOptions options = new DataLoadOptions();

options.LoadWith<Global>(p => p.Category);
options.AssociateWith<Global>(p => p.Category.OrderBy(o => o.SortOrder));
options.LoadWith<Category>(p => p.ItemTypes);
options.AssociateWith<Category>(p => p.ItemTypes.OrderBy(o => o.SortOrder));

cdc.LoadOptions = options;

TraceTextWriter traceWriter = new TraceTextWriter();
cdc.Log = traceWriter;

var query =
from g in cdc.Global
where g.active == true && g.globalid == 41
select g;

var globalList = query.ToList();

// In this case I have hardcoded an id while I figure this out
// but intend on trying to figure out a way to include something like globalid in (#,#,#)
foreach (var g in globalList)
{

   // I only have one result set, but if I had multiple globals this would run however many times and execute multiple queries like it does farther down in the hierarchy 
    List<Category> categoryList = g.category.ToList<Category>();

    // Doing some processing that sticks parent record into a hierarchical collection

    var categories = (from comp in categoryList
        where comp.Type == i 
        select comp).ToList<Category>();

    foreach (var c in categories)
    {
        // Doing some processing that stick child records into a hierarchical collection
        // Here is where multiple queries are run for each type collection in the category
        // I want to somehow run this above the loop once where I can get all the Items for the categories
        // And just do a filter

        List<ItemType> typeList = c.ItemTypes.ToList<ItemType>();

        var itemTypes = (from cat in TypeList
                where cat.itemLevel == 2
                select cat).ToList<ItemType>();

        foreach (var t in itemTypes)
        {
           // Doing some processing that stick child records into a hierarchical collection                            
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

"List typeList = c.ItemTypes.ToList();"
这行在foreach中被执行多次,并且执行查询以获取结果,并且我理解为什么在某种程度上,但我认为它会急于加载Loadwith作为选项,就像用一个查询获取所有内容一样.

所以基本上我会期望L2S在幕后获取一个查询中的"全局"记录,获取任何主键值,使用一个查询获取"类别"子项.获取这些结果并将其粘贴到与全球相关的集合中.然后获取所有类别键并执行一个查询以获取itemtype子项并将其链接到其关联的集合中.按顺序排列的东西(从ItemTypes中选择*其中的CategoryID(从类别中选择categoryID in(#,#,#))

我想知道如何正确地用最少的查询来加载关联的子项,以及可能如何完成我的例程,一般不知道我需要多长时间来构建层次结构,但是给定父实体,抓住所有关联的子集合然后执行我需要做什么.

Shi*_*iji 5

Linq to SQL在急切加载方面有一些限制.

因此,Linq To SQL中的Eager Load只能一次加载一个级别.由于它是延迟加载,使用加载选项,我们仍将在根级别每行(或对象)发出一个查询,这是我们真正想避免的数据库备用.这是急切加载的一点,以节省数据库.LINQ to SQL为层次结构发出查询的方式将通过log(n)降低性能,其中n是根对象的数量.调用ToList不会改变行为,但它会控制何时将所有查询发布到数据库.

详情见:

http://www.cnblogs.com/cw_volcano/archive/2012/07/31/2616729.html

  • @ShirazBhaiji谢谢!我最终通过使用显式LINQ扩展而不是LINQ查询语法解决了这个问题,如[本文](https://msdn.microsoft.com/en-us/data/jj574232.aspx#eagerLevels)中所述. (2认同)