相关疑难解决方法(0)

在Entity Framework LINQ查询中使用IEnumerable.Contains时如何避免查询计划重新编译?

我使用Entity Framework(v6.1.1)执行以下LINQ查询:

private IList<Customer> GetFullCustomers(IEnumerable<int> customersIds)
{
    IQueryable<Customer> fullCustomerQuery = GetFullQuery();
    return fullCustomerQuery.Where(c => customersIds.Contains(c.Id)).ToList();
}
Run Code Online (Sandbox Code Playgroud)

这个查询被翻译成相当不错的SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[FirstName] AS [FirstName]
-- ...
FROM [dbo].[Customer] AS [Extent1]
WHERE [Extent1].[Id] IN (1, 2, 3, 5)
Run Code Online (Sandbox Code Playgroud)

但是,我在查询编译阶段获得了非常显着的性能影响.呼叫:

ELinqQueryState.GetExecutionPlan(MergeOption? forMergeOption) 
Run Code Online (Sandbox Code Playgroud)

占用每个请求约50%的时间.深入研究,结果是每次我传递不同的customersIds时都会重新编译查询.根据MSDN文章,这是一个正常现象,因为IEnumerable的是在查询中使用被认为是挥发性的,并且是缓存的SQL的一部分.这就是为什么SQL对于customersIds的每个不同组合都是不同的,并且它总是具有用于从缓存中获取编译查询的不同哈希.

现在问题是:如何在仍然查询多个customersIds时避免重新编译?

linq performance linq-to-entities entity-framework

31
推荐指数
2
解决办法
3298
查看次数

为什么实体框架在直接选择语句中比Dapper执行得更快

我是新手使用ORM处理数据库,目前我正在制作一个新项目,我必须决定是否使用Entity Framework或Dapper.我读了许多文章说Dapper比实体框架更快.

所以我使用Dapper创建了两个简单的原型项目,另一个使用Entity Framework和一个函数从一个表中获取所有行.表格架构如下图所示

表格式

以及两个项目的代码如下

对于Dapper项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Emp> emplist = cn.Query<Emp>(@"Select * From Employees");
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());
Run Code Online (Sandbox Code Playgroud)

实体框架项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());
Run Code Online (Sandbox Code Playgroud)

经过多次尝试上面的代码只有我第一次运行项目时,dapper代码会更快,在这第一次之后我总是从实体框架项目中获得更好的结果我还尝试了以下关于实体框架项目的语句来阻止懒惰装载

hrctx.Configuration.LazyLoadingEnabled = false;
Run Code Online (Sandbox Code Playgroud)

但是,除了第一次以外,EF的表现仍然相同.

虽然网上的所有文章都相反,但任何人都能给我解释或指导EF在这个样本中的速度更快

更新

我已经改变了实体样本中的代码行

IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();
Run Code Online (Sandbox Code Playgroud)

使用某些文章中提到的AsNoTracking会停止实体框架缓存,停止缓存后,dapper样本表现更好,(但不是很大的区别)

c# entity-framework dapper

27
推荐指数
2
解决办法
3万
查看次数