如何在 Dapper 中使用“Where In”

Posted

技术标签:

【中文标题】如何在 Dapper 中使用“Where In”【英文标题】:How do I use 'Where In' in Dapper 【发布时间】:2013-11-24 19:32:45 【问题描述】:

一段时间以来,我一直在尝试在 Dapper 中使用 IEnumerable<string>WHERE IN 子句,但没有成功。

在文档中,确实说 IEnumerable<int> 支持在 WHERE IN 中使用,但我什至无法让它工作。

Dapper allow you to pass in IEnumerable<int> and will automatically parameterize your query.

我不断收到的错误消息是 Sql 语法错误。 Incorrect syntax near ','.

我整理了一些测试代码,希望能证明我想要实现的目标。


string connString = "Server=*.*.*.*;Database=*;User Id=*;Password=*;";

string sqlStringIn = @"SELECT StringText FROM 
                (SELECT 1 ID, 'A' StringID, 'This is a test' StringText
                UNION SELECT 2 ID, 'B' StringID, 'Another test' StringText
                UNION SELECT 3 ID, 'C' StringID, 'And another' StringText
                UNION SELECT 4 ID, 'D' StringID, 'and again' StringText
                UNION SELECT 5 ID, 'E' StringID, 'yet again' StringText) data
                WHERE StringId IN (@str)";

string sqlIntegerIn = @"SELECT StringText FROM 
                (SELECT 1 ID, 'A' StringID, 'This is a test' StringText
                UNION SELECT 2 ID, 'B' StringID, 'Another test' StringText
                UNION SELECT 3 ID, 'C' StringID, 'And another' StringText
                UNION SELECT 4 ID, 'D' StringID, 'and again' StringText
                UNION SELECT 5 ID, 'E' StringID, 'yet again' StringText) data
                WHERE ID IN (@integer)";


using (SqlConnection conn = new SqlConnection(connString))

    conn.Open();

    List<int> integers = new List<int> 1, 2, 3 ;
    List<string> strings = new List<string>  "A", "B", "C" ;

    var parameters = new str = strings, integer = integers ;

    //fails here
    IEnumerable<string> intTest = conn.Query<string>(sqlIntegerIn, parameters, commandType: System.Data.CommandType.Text);

    //and here
    IEnumerable<string> stringTest = conn.Query<string>(sqlStringIn, parameters, commandType: System.Data.CommandType.Text);


【问题讨论】:

你为什么不使用 Linq ? Dapper 有一个助手库可以为您完成这项工作:sqlinq.codeplex.com/releases/view/88056 @Aybe 没必要; dapper 明确处理这种情况 【参考方案1】:

要执行此处需要的操作,dapper 需要动态更改 SQL - 所以它需要真正确保它正在做正确的事情。常规有效 SQL 语法包括括号:

WHERE StringId IN (@str)

为了消除歧义,voodoo dapper 语法 省略括号:

WHERE StringId IN @str

如果检测到这一点,它会查找名为 str 的参数,并将其扩展为以下之一:

WHERE 1=0 -- if no values
WHERE StringId = @str -- if exactly one value
WHERE StringId IN (@str0, @str1, ...) -- if more than one value

但简短的版本:删除括号。

【讨论】:

@Marc 如果列表超过最大值,这不会倒下吗?查看错误:传入请求的参数过多。服务器最大支持2100 @csetzkorn 如果您使用非常大的设备,TVP 和INNER JOIN 可能比IN 更好; dapper 完全支持 TVP。我不想做的是将每个不同供应商的不同技术限制硬编码到库中 感谢 TVP 听起来不错。我想我可以将它包含在我的参数化 sql 中吗? (例如***.com/questions/26466485/…) 谢谢。我仍然不确定该怎么做。能否请您看一下:***.com/questions/26468710/… @MarcGravell 只有在传入的对象上只有一个 IEnumerable 参数时才有效,或者是否还有其他属性? var parameters = new assemblyName, entityIds = listOfIds.ToArray() ;【参考方案2】:

如果您有兴趣处理空列表,我想添加一个重要说明,也就是将IN 子句设置为optional。我通过添加一个包含计数的属性来做到这一点,例如public int InClauseCount =&gt; InClauseList?.Length ?? 0;

然后像这样在sql中使用计数...

Select field1, field2
from Table1
where (some condition)
AND (@InClauseCount = 0 OR field1 IN @InClauseList)

我希望这可以帮助那里的人。我花了太长时间试图解决这个问题,部分原因是我是 Dapper 的新手。

【讨论】:

以上是关于如何在 Dapper 中使用“Where In”的主要内容,如果未能解决你的问题,请参考以下文章

mysql中 where in 用法详解

mysql中 where in 用法详解

如何在 laravel DB:raw 中使用 count() WHERE IN

如何在使用 MySQL 2 的 Rails 3 项目中使用 WHERE IN?

mysql中 where in 用法详解

如何在 Doctrine 查询生成器中进行多个 WHERE IN 列查询?