c# - 参数化查询的糟糕 Dapper 性能

标签 c# performance entity-framework dapper

当我遇到一个奇怪的问题时,我正在研究将我们的一些 EF6 代码移植到 Dapper 以获得更好的性能。单行查询在 Dapper 中花费的时间是在 EF 中的近 10 倍。它看起来像这样:

using (IDbConnection conn = new SqlConnection("connection string"))
{                
      row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
                                          new {ID = id}))
                                  .FirstOrDefault();
}

此查询针对具有大约 80 列的 View ,并且 EF 版本使用完全相同的查询和相同的模型。作为引用,这是 EF 版本:

row = context.ReportViews.Where(s => s.ID == id).FirstOrDefault();

我考虑到第一个查询可能会很慢,所以我在“预热”期后进行了测量。我认为重用 EF 模型可能会出现问题,因此我创建了一个简单的 POCO 作为模型。这些都没有用。所以我玩弄它,尝试不同的东西,并决定尝试使用 SQL 注入(inject)连接 SQL 语句。

using (IDbConnection conn = new SqlConnection("connection string"))
{                
      row = conn.Query<ReportView>(string.Format("select * from ReportView where ID = '{0}'", 
            id)).FirstOrDefault();
}

这个查询实际上比 EF 查询更快。

那么这里发生了什么?为什么参数化查询这么慢?

最佳答案

根据您的最后一个示例,您的列似乎很可能是 varchar,但是当您使用参数化查询时,参数将作为 nvarchar 发送。由于 nvarchar 到 varchar 可能涉及数据丢失,SQL 将表中的每个值转换为 nvarchar 以进行比较。可以想象,转换每一行以进行比较很慢,并且会阻止使用索引。

要解决此问题,您有两种选择:

如果您的数据库根本不使用 nvarchar,您可以在应用程序启动期间简单地更改映射:

Dapper.SqlMapper.AddTypeMap(typeof(string), System.Data.DbType.AnsiString);

否则您可以根据查询更改它:

row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
                              new {ID = new DbString { Value = id, IsAnsi = true }})
                              .FirstOrDefault();

关于c# - 参数化查询的糟糕 Dapper 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38533752/

相关文章:

c# - 从缓存列表查询 IQuery 返回 null 异常

c# - ASP.NET Core Web 应用程序 - 如何上传大文件

c# - C# 中串行端口的多端口异步 I/O

performance - Perl 中大型哈希表的快速加载

c# - C#中的字符串解析

c# - 对同一实体同时使用多对多和一对多

c# - 如何创建一系列字母和数字的字符串组合?

c# - 使用正则表达式获取每个反斜杠之间的字符串

c# - 如何在输入值时停止Excel-DNA函数计算

asp.net - DbContext VS ObjectContext