【发布时间】:2014-04-28 23:18:50
【问题描述】:
Dapper(1.13 Noobget 包)创建不同的 SQL 语句,具体取决于它是用于普通的 ADO.NET 数据库连接还是用于修饰的 mini-profiler 数据库连接。
示例代码(用 Postgresql 测试)
用途:
using System.Linq;
using Dapper;
using Npgsql;
using NUnit.Framework;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;
Test1 使用普通的 ADO.NET 连接并且失败:
[TestFixture]
public class DapperTests {
private const string cnnstr = "HOST=...;DATABASE=...;USER ID=...;PASSWORD=...;";
[Test]
public void Test1() {
using (var cnn = new NpgsqlConnection(cnnstr)) {
cnn.Open();
// The following line fails:
cnn.Query<int>("SELECT 1 WHERE 42 IN @Items", new {Items = new[] {41, 42, 43}}).Single();
// Npgsql.NpgsqlException : ERROR: 42883: operator does not exist: integer = integer[]
}
}
Test2 使用围绕 ADO.NET 连接的小型分析器连接,并且成功:
[Test]
public void Test2() {
using (var cnn = new NpgsqlConnection(cnnstr))
using (var profiled = new ProfiledDbConnection(cnn, MiniProfiler.Start())) {
profiled.Open();
int result = profiled.Query<int>("SELECT 1 WHERE 42 IN @Items", new {Items = new[] {41, 42, 43}}).Single();
Assert.AreEqual(1, result);
}
}
}
查看生成的 SQL 就很清楚为什么 Test1 失败了:
- Test1 的 SQL:SELECT 1 WHERE 42 IN ((array[41,42,43])::int4[])
- Test2 的 SQL:SELECT 1 WHERE 42 IN (((41)),((42)),((43)))
数组不支持 IN。
为什么 dapper 在使用/不使用配置文件连接时会生成不同的 SQL?
为什么它会生成一个带有普通连接的数组[...]?由于dapper's docs,它应该生成一个元组:
【问题讨论】:
-
在这两种情况下,您究竟是从哪里获取 sql 的?我想知道差异是否主要在于它的呈现方式。无论此处的提供者如何,Dapper 都会做同样的事情
-
这是第二次报告与 postgres 相关;我怀疑它实际上是 postgres 提供程序在这里弄得一团糟,因为那根本不是 dapper 发出的;我将不得不调查
-
我直接从服务器日志中获取 sql(在启用了 sql 日志记录的控制台中运行它)。导致问题的原因是 sql 根据是否使用/未使用配置文件的连接而有所不同..
-
PS:我注意到 mini-profiler 实际上包含一个 dapper 的副本(它在 StackExchange.Profiling.Helpers.Dapper 中是公开的)。无论如何,这可以安全地用于使用迷你分析器的项目中,还是有可能在以后变成内部的?我认为这个版本的 dapper 包含一些(有用的)更改/错误修复,这些更改/错误修复未包含在官方 dapper 中。
-
@MarcGravell 我调查并找到了问题的原因,但没有很好的解决方案。请在下面查看我的答案。
标签: dapper npgsql mvc-mini-profiler