Dapper 存储过程在将 IEnumerable 传递给它时指定了太多参数

Dapper stored procedure has too many arguments specified when passing IEnumerable to it

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

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

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

"Procedure or function GetAlgorithmsByName has too many arguments specified."

我做错了什么?如何使用 dapper 将 IEnumerable<string> 传递给存储过程?

在您的存储过程中期望 [Item] [NVARCHAR](MAX),这意味着一项而您正在传递 IEnumerable<string> names。这就是您收到错误的原因。

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

  1. XML
  2. CREATE TYPE NameList AS TABLE ( Name Varchar(100) );
  3. 一样使用table-valued parameters
  4. 使用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);
   }

Table 有价值的参数使用起来并不简单;一种方法是通过 Dapper 在 DataTable 上添加的扩展方法(类似于 AsTableValuedParameter),但是:它不像 IEnumerable<T> 那样简单地工作——至少,今天不是。你也可能不需要 DynamicParameters 这里。

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

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

检查此 link 并尝试