Dapper的IN子句支持我做错了什么?

时间:2016-07-06 21:20:13

标签: sql-server dapper

我正在尝试使用Dapper(v1.42)支持自动扩展IN子句的查询参数。我的查询如下:

var records = db.Query(
    "SELECT [IdCol], [OtherCol], [TinyIntCol], [TextCol] FROM [Tbl] WHERE [FilterCol] = @filterVal AND [TinyIntCol] IN @byteVals",
    new { filterVal = ..., byteVals = flag ? new byte[] { Constants.Byte1, Constants.Byte2 } : new byte[] { Constants.Byte1 } }
);

但是会导致 System.Data.SqlClient.SqlException(0x80131904):'@byteVals'附近的语法不正确。

我一定是做错了,但我不确定是什么。请告诉我我犯的是什么样的白痴。谢谢!

1 个答案:

答案 0 :(得分:1)

问题在于使用字节数组,Dapper将始终将字节数组作为单个二进制值传递 - 查询文本具有“IN”子句的事实不会改变它(请参阅@Damien_The_Unbeliever的注释)

为了说明,下面的工作(基于NORTHWND数据库,因为我已经掌握了)因为参数扩展正在使用int数组 -

var results = db.Query<Product>(
    "SELECT * FROM Products WHERE ProductId IN @ids",
    new
    {
        ids = new [] { 1, 2 } // This works (int array)
    }
);

..但是以下失败,它尝试传递一个字节数组 -

var results = db.Query<Product>(
    "SELECT * FROM Products WHERE ProductId IN @ids",
    new
    {
        ids = new byte[] { 1, 2 } // This fails (byte array)
    }
);

使用SQL事件探查器,第一个int-array方法会产生以下查询:

exec sp_executesql
    N'SELECT * FROM Products WHERE ProductId IN (@ids1,@ids2)',
    N'@ids1 int,@ids2 int',
    @ids1=1,
    @ids2=2

您可以清楚地看到传递的各个参数。

字节数组方法导致以下查询:

exec sp_executesql
    N'SELECT * FROM Products WHERE ProductId IN @ids',
    N'@ids varbinary(2)',
    @ids=0x0102

这里,“@ids”参数作为单个值传递,而不是扩展为单个值 - 这就是导致问题的原因。

您应该能够通过使用字节值来填充int数组来解决它。