C#
我将LINQ to SQL结果投影到强类型类:Parent和Child。 这两个查询之间的性能差异很大:
慢速查询 - 从DataContext记录显示,正在为每个父进程分别调用数据库
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记录显示一个单一的数据库命中查询,返回所有需要的数据
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;
请注意:父和子是简单的类型,不是Table<TEntity>
类型。 父母与子女之间没有上下文关系。 子查询是特设的。
问题的症结:在第二个LINQ示例中,我实现了IQueriable
语句并且不调用ToList()
函数,出于某种原因,LINQ知道如何生成一个可以检索所需数据的单个查询。 我如何使用实际数据填充我的临时投影,就像在第一个查询中完成的一样? 另外,如果有人能帮助我更好地说出我的问题,我将不胜感激。
记住LINQ查询依赖于延期执行是很重要的。 在你的第二个查询中,你实际上并没有获取关于这些孩子的任何信息。 您已经创建了查询,但是您并未实际执行它们以获取这些查询的结果。 如果您要迭代列表,然后遍历每个项目的Children
集合,则会看到它花费的时间与第一个查询相同。
您的查询本身效率也很低。 您正在使用嵌套查询来表示Join
关系。 如果您使用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
我发现完成这个最快的方法是执行一个查询,返回所有结果,然后对所有结果进行分组。 确保在第一个查询上执行.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 });
您必须为数据加载设置正确的选项。
options.LoadWith<Document>(d => d.Metadata);
看这个
PS仅Include
LINQToEntity
。
上一篇: c#
下一篇: How can I deep clone an entity and avoid errors caused by navigation properties?