【问题标题】:Dapper stored procedure has too many arguments specified when passing IEnumerable to itDapper 存储过程在将 IEnumerable 传递给它时指定了太多参数
【发布时间】:2020-01-13 17:04:52
【问题描述】:

我正在通过这种方法调用我的程序:

public async Task<IEnumerable<Algorithm>> GetAlgorithmsByNameAsync(IEnumerable<string> names)
{
    var parameters = new DynamicParameters();
    parameters.Add("@names", names);

    var connection = _connection.GetOpenConnection();   
    return await connection.QueryAsync<Algorithm>("GetAlgorithmsByName", parameters, commandType: CommandType.StoredProcedure);
}

我的程序如下所示:

CREATE TYPE [dbo].[StringList] AS TABLE(
    [Item] [NVARCHAR](MAX) NULL
);

--PROCEDURE HERE--

CREATE PROCEDURE GetAlgorithmsByName

@names StringList READONLY -- my own type

AS
BEGIN
    SELECT ALgorithmId, Name From Algorithms WHERE Name IN (SELECT Item FROM @names)
END

从上面的代码,我得到一个错误:

“GetAlgorithmsByName 过程或函数指定的参数过多。”

我做错了什么?如何使用 dapper 将IEnumerable&lt;string&gt; 传递给存储过程?

【问题讨论】:

    标签: c# sql dapper


    【解决方案1】:

    使用表值参数并非易事;一种方法是通过 Dapper 在DataTable 上添加的扩展方法(类似于AsTableValuedParameter),但是:它不像IEnumerable&lt;T&gt; 那样简单——至少现在不是。你也可能不需要DynamicParameters

    如果您想要的只是一组字符串,那么一个非常实用的选择是查看 SQL Server 中内置的string_split API,如果您可以定义一个从未在数据中使用的分隔符标记。然后你可以只传递一个分隔字符串。

    【讨论】:

      【解决方案2】:

      在您的存储过程中期待[Item] [NVARCHAR](MAX),这意味着一个项目而您正在传递IEnumerable&lt;string&gt; names。所以这就是你收到错误的原因。

      有很多方法可以将字符串列表传递给 sp

      1. XML
      2. 使用table-valued parameters 就像CREATE TYPE NameList AS TABLE ( Name Varchar(100) );
      3. 使用names = "Name1, Name2, .. , Namen";然后使用sql可以使用T-SQL split string获取名单

      更新 您传递的参数不正确,让我们这样修复它

           using (var table = new DataTable()) 
           {
            table.Columns.Add("Item", typeof(string));
      
            for (int i = 0; i < names.length; i++)
              table.Rows.Add(i.ToString());
      
            var pList = new SqlParameter("@names", SqlDbType.Structured);
            pList.TypeName = "dbo.StringList";
            pList.Value = table;
      
            parameters.Add(pList);
         }
      

      【讨论】:

      • 您的第二个选项是 OP 在问题中的内容
      • 糟糕,对不起。让我更新我的答案。谢谢先生。
      • 我刚刚更新了我的答案,请看一下@Marc Gravell♦ 但是,在我看来,参数很简单,OP 不需要创建table-valued parameters ,应该使用选项 3 .
      • 最后的代码似乎忽略了 OP 使用的是 dapper,而不是原始 ADO.NET 的事实;数据表位看起来不错,但有一个扩展方法 - 类似于与 Dapper 一起使用的 AsTableValuedParameter
      • 感谢您的建议!当我回到我的项目时,我会尽快检查一切:)
      【解决方案3】:

      您可以使用 IEnumerable(动态)而不是 IEnumerable(字符串)。

      检查此链接并尝试How to Implement IEnumerable (dynamic)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-14
        • 2015-09-02
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 2016-04-05
        相关资源
        最近更新 更多