我在我的项目中使用EF核心2作为ORM。我在执行这个查询时遇到了这个问题:
var query = (from droitsGeo in _entities.DroitsGeos
join building in _entities.Batiments
on droitsGeo.IdPerimetre equals building.IdBatiment
where droitsGeo.IdUtilisateur == idUser &&
droitsGeo.IdClient == idClient &&
building.Valide == true &&
droitsGeo.IdNiveauPerimetre == geographicalLevel
orderby sort ascending
select new GeographicalModel
{
Id = building.IdBatiment,
IdParent = building.IdEtablissement,
Label = building.LibBatiment,
});
第一次执行大约5秒,第二次执行不到一秒,如下所示:
查询的第一次执行:
已用时间EF: 00:00:04.8562419
第一次执行查询后的 :
已用时间EF: 00:00:00.5496862
已用时间EF: 00:00:00.6658079
已用时间EF: 00:00:00.6176030
我使用存储过程也得到了同样的结果。
当我在sql Server中执行EF生成的SQL查询时,在不到一秒的时间内返回结果。
EF Core 2出了什么问题,或者我在配置中遗漏了什么?
发布于 2018-06-19 00:44:51
默认情况下,EF会跟踪您运行查询的所有实体。
当你第一次运行它的时候,磁道改变机制开始工作...这就是为什么它需要更长一点的时间。
您可以避免这种情况,特别是在编写查询时使用.AsNoTracking()
检索集合时。
看一看:
var items = DbContext.MyDbSet
.Include(SecondObject)
.AsNoTracking()
.ToList();
发布于 2018-12-11 06:31:44
EF内核需要使用反射来编译LINQ queries,因此第一次查询总是很慢。已存在GitHub issue here
发布于 2020-05-14 19:06:09
我有一个简单的想法,可以在存储过程和AutoMapper的帮助下解决这个问题。
创建一个返回所有所需列的存储过程,而不管这些列是否来自不同的表。一旦从存储过程接收到数据,并且在某个模型类中接收到对象,就可以使用AutoMapper仅将相关属性映射到其他类。请注意,我并不是在教你如何使用存储过程。我给你举一个例子,也许能更好地解释:
创建
SP_Result.cs
的模型类,以映射接收到的存储过程对象(在EF Core)CreateMap<SP_Result, ViewModel_A>(); CreateMap<SP_Result, ViewModel_B>();
。我想,您应该有一个请求和响应对象,它们可以用来代替ViewModels。在存储过程中使用AS
关键字对属性进行相应的命名。例如Select std_Name AS 'Name'
此映射将把各个属性映射到每个类。AutoMapper忽略在映射配置中提到的两个类中都不存在的属性。
如果您选择一个对象列表,其中每个对象都有自己的对象列表,则此方案通常会在EF中创建N+1个查询。实际上,如果您试图使用存储过程来实现这一点,您将不得不创建多个查询或多次运行存储过程(可能是在循环中),否则您最终将收到笛卡尔乘积。
https://stackoverflow.com/questions/50913897
复制相似问题