【问题标题】:Using Linq to SQL, how do I Eager Load all child and any nested children results使用 Linq to SQL,我如何渴望加载所有子级和任何嵌套的子级结果
【发布时间】:2009-07-28 00:20:39
【问题描述】:

我在 L2S 类 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                            
        }
    }
}

"列表类型列表 = c.ItemTypes.ToList();"
这条线在 foreach 中执行了无数次,并执行了一个查询来获取结果,我在一定程度上理解了原因,但我认为它会渴望加载 Loadwith 作为一个选项,就像用一个查询获取所有内容一样。

所以基本上我希望 L2S 在幕后在一个查询中获取“全局”记录,获取任何主键值,使用一个查询获取“类别”子项。获取这些结果并将它们粘贴到与全球相关的集合中。然后获取所有类别键并执行一个查询以获取 itemtype 子项并将它们链接到它们的关联集合中。 (Select * from ItemTypes Where CategoryID in (select categoryID from Categories where GlobalID in (#,#,#)) 顺序的东西

我想知道如何用最少的查询正确地预先加载关联的子项,以及如何完成我的例程,一般不知道我需要构建层次结构的深度,但是给定一个父实体,获取所有关联的子集合然后做我需要做的。

【问题讨论】:

    标签: c# asp.net linq-to-sql


    【解决方案1】:

    Linq to SQL 在预加载方面有一些限制。

    所以 Linq To SQL 中的 Eager Load 只是 一次急切地加载一个级别。 因为它用于延迟加载,所以使用 Load 选项我们仍然会发出一个查询 根级别的每行(或对象) 这是我们真正想要的 避免备用数据库。哪一个 有点急切 加载,以备用数据库。这 LINQ to SQL 发出查询的方式 层次结构会减少 log(n) 的性能,其中 n 是 根对象的数量。调用列表 不会改变行为,但会 控制所有查询的时间 将发布到数据库。

    详情见:

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

    【讨论】:

    • 感谢 Shiraz,这篇文章准确地描述了我遇到的问题。我只是假设我必须设置错误并且那里有解决方案。我猜不会!事实上,我实际上在我的代码中实现了你在他的“应该如何?”中看到的内容。部分。我只是不认为我应该这样做。
    • @Breadtruck 链接已失效,您能否更新此答案以提供相关代码?
    • @Dan 我修复了链接
    • @ShirazBhaiji 谢谢!我最终通过使用显式 LINQ 扩展而不是 LINQ 查询语法解决了这个问题,如this article 中所述。
    • @Simon_Weaver 不知道这些技术叫什么,我只是更喜欢在迭代子实体 1000 次时生成单个 SQL 服务器请求而不是 1000 个请求的方法。
    【解决方案2】:

    我确信这可以做得更好,但我的代码使用最少的查询。每级一个。这显然不是真正使用 L2S 进行急切加载,但如果有人知道正确的方式,我想知道以供将来参考。

        var query =
        from g in cdc.Global
        where g.active == true && g.globalId == 41
        select g;
    
        var globalList = query.ToList();
    
        List<Category> categoryList = g.category.ToList<Category>();
    
        var categoryIds = from c in cdc.Category
                    where c.globalId == g.globalId
                    select c.categoryId;
    
        var types = from t in cdc.ItemTypes
                    where categoryIds.Any(i => i == t.categoryId)
                    select t;
    
        List<ItemType> TypeList = types.ToList<ItemType>();
    
        var items = from i in cdc.Items
                    from d in cdc.ItemData
                    where i.ItemId == d.ItemId && d.labelId == 1
                    where types.Any(i => i == r.ItemTypes)
                    select new 
                        {
                            i.Id, 
                            // A Bunch of more fields shortened for berevity
                            d.Data    
                        };
    
        var ItemList = items.ToList();
    
        // Keep on going down the hierarchy if you need more child results
        // Do your processing psuedocode
        for each item in list
            filter child list
            for each item in child list
                .....
        // 
    

    不介意知道如何使用泛型和给定顶级表的递归方法来完成这一切

    【讨论】:

    • 你好,你有想过这个吗?
    • 我没有,我再也没有重新审视这个问题。
    • 这应该被删除,因为它不是一个答案,而是一个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2014-01-04
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多