当我遇到一个奇怪的问题时,我正在研究将我们的一些 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/