6

我将 LINQ to SQL 结果投影到强类型类:父类和子类。这两个查询之间的性能差异很大:

慢查询 - 从 DataContext 记录显示正在为每个父级单独调用 db

var q = from p in parenttable
        select new Parent()
        {
            id = p.id,
            Children = (from c in childtable
                        where c.parentid = p.id
                        select c).ToList()
        }
return q.ToList()  //SLOW

快速查询 - 从 DataContext 记录显示单个 db hit 查询,该查询返回所有必需的数据

var q = from p in parenttable
        select new Parent()
        {
            id = p.id,
            Children = from c in childtable
                        where c.parentid = p.id
                        select c
        }
return q.ToList()  //FAST

我想强制 LINQ 使用第二个示例的单查询样式,但直接使用它们的 Children 对象填充 Parent 类。否则,Children 属性是一个IQuerierable<Child>必须被查询才能公开 Child 对象的属性。

引用的问题似乎没有解决我的情况。使用 db.LoadOptions 不起作用。也许它要求类型是在 DataContext 中注册的 TEntity。

   DataLoadOptions options = new DataLoadOptions();
   options.LoadWith<Parent>(p => p.Children);
   db.LoadOptions = options;

请注意:Parent 和 Child 是简单类型,而不是Table<TEntity>类型。Parent 和 Child 之间没有上下文关系。子查询是临时的。

问题的症结:在第二个 LINQ 示例中,我实现了IQueriable语句并且不调用ToList()函数,并且由于某种原因 LINQ 知道如何生成一个可以检索所有必需数据的单个查询。如何使用第一个查询中完成的实际数据填充我的临时投影?另外,如果有人可以帮助我更好地表达我的问题,我将不胜感激。

4

4 回答 4

7

重要的是要记住 LINQ 查询依赖于延迟执行。在您的第二个查询中,您实际上并没有获取有关孩子的任何信息。您已经创建了查询,但实际上并没有执行它们来获取这些查询的结果。如果您要迭代列表,然后迭代Children每个项目的集合,您会发现它花费的时间与第一个查询一样多。

您的查询本质上也非常低效。您正在使用嵌套查询来表示Join关系。如果您改用 a Join,则查询提供程序和数据库都可以对查询进行适当优化,从而更快地执行。您可能还需要调整数据库上的索引以提高性能。以下是连接的外观:

var q = from p in parenttable
        join child in childtable
        on p.id equals child.parentid into children
        select new Parent()
        {
            id = p.id,
            Children = children.ToList(),
        }
return q.ToList()  //SLOW
于 2013-04-29T14:19:00.330 回答
1

我发现完成此操作的最快方法是执行返回所有结果的查询,然后对所有结果进行分组。确保在第一个查询上执行 .ToList() ,这样第二个查询就不会进行很多调用。

这里r应该有你想要只用一个数据库查询来完成的事情。

            var q = from p in parenttable
                    join c in childtable on p.id equals c.parentid
                    select c).ToList();
            var r = q.GroupBy(x => x.parentid).Select(x => new { id = x.Key, Children=x });
于 2013-04-29T14:11:51.420 回答
0

第二个查询很快,正是因为没有填充儿童。

第一个很慢,只是因为儿童人口众多。

选择最适合您需求的一款,您根本无法同时拥有它们的功能!

编辑:

正如@Servy所说:

在您的第二个查询中,您实际上并没有获取有关孩子的任何信息。您已经创建了查询,但实际上并没有执行它们来获取这些查询的结果。如果您要迭代列表,然后迭代每个项目的 Children 集合,您会发现它花费的时间与第一个查询一样多。

于 2013-04-29T13:57:52.520 回答
0

您必须为数据加载设置正确的选项。

options.LoadWith<Document>(d => d.Metadata);

看看这个

PSIncludeLINQToEntity唯一。

于 2013-04-26T15:56:55.670 回答