Dapper:过程或函数指定了太多参数

问题描述 投票:0回答:6

使用 Dapper 调用存储过程时,我收到以下错误:

Procedure or function has too many arguments specified

我正在使用 DynamicParameters 将简单参数列表添加到查询中。

参数代码如下:

var parameters = new DynamicParameters();
parameters.Add(p.Name, p.Value, direction: p.Mode);

查询代码如下所示:

var result = _connection.Query<T>(
            string.Format("{0}.{1}", request.SchemaName, request.StoredProcedureName),
            parameters,
            commandType: CommandType.StoredProcedure,
            transaction: _transaction);

Profiler 中执行的 sql 如下所示:

exec dbo.storedProcedureName @ParameterNames1=N'ParameterName',@ParameterNames2=N'ParameterName',@RemoveUnused=1

@ParameterNames1 根本不是参数的调用方式。实际上,名称是作为值传入的(N'ParameterName')。 @RemoveUnused 参数对我来说似乎完全是随机的,因为它根本不会出现在调用代码中。

完整代码可以在这里找到:GitHub 项目 第 61 和 228 行。

编辑:我发现问题是由于两次调用相同的过程且结果集不同而引起的。所以第一次我用 Query 调用它,第二次用 Query 调用它。为什么 Dapper 在这种情况下遇到麻烦仍然是个谜。

sql .net sql-server dapper
6个回答
3
投票

我最近遇到了这个问题,这似乎是由以下原因引起的:

  • 您的存储过程可以返回多个数据集(可能基于 条件参数)。
  • 您正在使用调用存储过程
    Query<T>()
    代替
    QueryMultiple()
    ,然后映射数据集 通过
    Read<T>

我们最近从旧版本的 Dapper 升级到 v1.4,以支持表变量参数,并且我们开始遇到这种行为,这是升级的直接结果。

解决方案:

将基于

Query<T>
的代码转换为
QueryMultiple
实现。


1
投票

我根本无法重现这个:

public void SO25069578_DynamicParams_Procs()
{
    var parameters = new DynamicParameters();
    parameters.Add("foo", "bar");
    try { connection.Execute("drop proc SO25069578"); } catch { }
    connection.Execute("create proc SO25069578 @foo nvarchar(max) as select @foo as [X]");
    var tran = connection.BeginTransaction(); // gist used transaction; behaves the same either way, though
    var row = connection.Query<HazX>("SO25069578", parameters,
        commandType: CommandType.StoredProcedure, transaction: tran).Single();
    tran.Rollback();
    row.X.IsEqualTo("bar");
}
public class HazX
{
    public string X { get; set; }
}

工作正常。 RemoveUnused上有

is
一个
DynamicParameters
属性,位:使用动态参数时,不应该添加。我什至尝试过使用基于模板的构造函数:

parameters = new DynamicParameters(parameters);

但再次强调:这很好用。您是否有可能使用“非常非常旧”的 dapper 版本?你用的是什么版本?


1
投票

要重现此情况,您需要一个基于输入参数的存储过程,该存储过程可以返回 1 或 2 个(多于 1 个)结果集。在代码中,我也使用 2 种不同的扩展方法来调用它(

QueryMultipleAsync

将参数设置为 1 或 true,

QueryAsync
将参数设置为 0 或 false)。如果您的测试最终首先调用 SP 返回多个结果集,则需要 1 个结果集的后续调用将失败并出现此错误。

我解决这个问题的唯一方法是将 SP 分成 2 个,这样它们就有不同的名称。

作为参考,这是我如何称呼 SP 的:

var data = await sqlConnection.QueryAsync<T>( StoredProcedureName, parms, transaction: null, commandTimeout: null, commandType: CommandType.StoredProcedure)

var data = await sqlConnection.QueryMultipleAsync( StoredProcedureName, param: p, commandType: CommandType.StoredProcedure) .Map<Type1, Type2, long> ( o1 => o1.Id, o2 => o2.FkId ?? 0, (o1, o2) => { o1.Children = o2.ToList(); } );



1
投票

var reader = conn.QueryMultiple (spName, pars, commandType: CommandType.StoredProcedure);

对此:

var cmd = new CommandDefinition (spName, pars, commandType: CommandType.StoredProcedure, flags: CommandFlags.NoCache); var reader = conn.QueryMultiple (cmd);



0
投票
对同一 SQL 存储过程的第一次调用是通过 .QueryMultiple 进行的。 使用 .QuerySingleOrDefault 再次调用带有参数的相同过程会导致参数为原始问题中提到的 ParameterNames1 和 RemoveUnused。



0
投票
QueryMultipleAsync

QueryAsync
调用存储过程时遇到同样的问题(以相反的顺序工作!)。
我用一个可怕的解决方法解决了:使用 

QueryMultipleAsync

时,我在存储过程名称的末尾添加了一个空格。 像这样:

sql += " ";
var gridReader = await connection.QueryMultipleAsync(sql, param, dbTransaction, commandTimeout, commandType);

	
© www.soinside.com 2019 - 2024. All rights reserved.