gpt4 book ai didi

c# - Include 的 Entity Framework 性能问题

转载 作者:太空宇宙 更新时间:2023-11-03 21:36:47 28 4
gpt4 key购买 nike

我想知道哪个具有更好的性能

 var allocations = 
Catalog.ResourceAllocations
.Where(c => c.Pet.Key == petKey && c.Pet.Owner.Key == ownerKey)
.Include(k => k.Appointment)
.Include(k => k.Service)
.Include(k => k.Appointment.Provider.Address)
.ToList();

var allocations = 
Catalog.ResourceAllocations
.Where(c => c.Pet.Key == petKey && c.Pet.Owner.Key == ownerKey)
.Include(k => k.Appointment.Provider.Address)
.Include(k => k.Service)
.ToList();

最佳答案

DbQuery<T>.Include(path) 的文档指出(请阅读末尾的注意 - 它描述了路径包含的工作原理):

Paths are all-inclusive. For example, if an include call indicates Include("Orders.OrderLines"), not only will OrderLines be included, but also Orders.

所以 k.Appointment.Provider.Address将包括 k.Appointment反正。即使没有性能损失,第二个查询也更好,因为它不包含重复的包含定义。

更新:数据库查询不会有性能差异,因为两个 LINQ 查询将导致生成相同的 SQL 查询(好吧,LEFT OUTER JOINS 的顺序可能不同)。但是在查询生成上会有很小的性能差异,因为当你包含一些路径时,新的 ObjectQuery将生成(是的,每个 Include 都会创建新查询而不是修改现有查询)。

注意: 有趣的是知道为什么没有区别 - 我对 Entity Framework 6 源进行了一些调查,发现了 EF 如何收集应包含的路径。有内部密封类Span它保存路径集合以确定哪些元素包含在查询中。 SpanPath非常简单 - 它只是字符串列表的包装器,代表要包含的导航:

internal class SpanPath
{
// you can think naviagations as path splitted by dots
public readonly List<string> Navigations;
// ...
}

Span是一个包含所有包含路径的类:

internal sealed class Span
{
private readonly List<SpanPath> _spanList = new List<SpanPath>();

public void Include(string path)
{
Check.NotEmpty(path, "path");
SpanPath spanPath = new SpanPath(ParsePath(path));
this.AddSpanPath(spanPath);
}

internal void AddSpanPath(SpanPath spanPath)
{
if (this.ValidateSpanPath(spanPath))
{
this.RemoveExistingSubPaths(spanPath);
this._spanList.Add(spanPath);
}
}

private bool ValidateSpanPath(SpanPath spanPath)
{
for (int i = 0; i < this._spanList.Count; i++)
{
if (spanPath.IsSubPath(this._spanList[i]))
return false;
}

return true;
}
}

所以,这是发生的事情 - 当您包含新路径时,则:

  1. 它被拆分成字符串列表并包装到 SpanPath 中
  2. 如果当前路径是某个已添加路径的子路径,那么我们就忽略它
  3. 否则我们检查我们的导航中是否存在当前路径的子路径。如果是这样,我们删除所有子路径
  4. 现在我们可以添加新路径了。

当您包含 Appointment.Provider.Address 时第一种情况下的路径,然后是 Appointment path 将在步骤 #3 中删除,因为它是 Appointment.Provider.Address 的子路径.

总结:

不要在查询中显式包含子路径 - 这会导致创建新的 ObjectQuery 实例,并且不会影响生成的查询。它将被忽略,或者在您添加包含此路径的路径时将其删除。

关于c# - Include 的 Entity Framework 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21327482/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com