我有一个查询,加载速度非常慢。我认为这是很不对劲,但是我不明白为什么。 在我的应用程序中,我有一个实体KeyText:
{{ }}
大多数其他实体都具有多个这些键文本。它只是填充组合框的一种简单方法。 因此,如果我这样通过ef内核加载:(那么ThenInclude lambda中的所有内容都是KeyText)
public class KeyText
int Id
Group Group
string Text
在实际应用中,它最多可以加载20秒,这非常荒谬 数据量。我说的像是5个收藏集中的5个条目。
但是,如果我这样加载:
context.Companies
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
它立即加载。为什么是这样?第一个查询错了吗?
答案 0 :(得分:0)
假设您有5家公司,每家公司有5个地址:
context.Companies
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
此代码生成Sql的5 * 5 = 25个左联接,每个联接由3个联接(公司*地址*类型)组成
var companies = context.Companies;
companies.adresses = context.Adresses
.Include(a => a.AdressType)
.Include(a => a.CityType)
.Include(a => a.AnotherKeyText)
.Include(a => a.DifferentKeyText);
此代码代表Sql生成5个左联接,每个联接由2个联接(地址*类型)组成
因此,很明显,第一种方法会严重损害您的性能。
无论如何,请尽量不使用Include
。而是使用Join
和Select
表达式加载所需的最小数据量。
答案 1 :(得分:0)
另一个在 EF 中加快查询速度的选项是使用.AsNoTracking()
var companies = context.Companies.AsNoTracking();
companies.adresses = context.Adresses.AsNoTracking()
.Include(a => a.AdressType)
.Include(a => a.CityType)
.Include(a => a.AnotherKeyText)
.Include(a => a.DifferentKeyText)
context.Companies.AsNoTracking()
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
在只读方案中使用结果时,没有跟踪查询很有用。由于不需要设置更改跟踪信息,因此执行起来更快。如果您不需要更新从数据库中检索到的实体,则应使用无跟踪查询。您可以将单个查询交换为无跟踪
默认情况下,返回实体类型的查询正在跟踪。这意味着您可以对这些实体实例进行更改,并使这些更改由SaveChanges()
保留。
默认情况下,当您从数据库加载数据时,ChangeTracker
已跟踪所有记录,这将导致速度和内存分配略有下降。