使用 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 在这种情况下遇到麻烦仍然是个谜。
我最近遇到了这个问题,这似乎是由以下原因引起的:
Query<T>()
代替QueryMultiple()
,然后映射数据集
通过Read<T>
。我们最近从旧版本的 Dapper 升级到 v1.4,以支持表变量参数,并且我们开始遇到这种行为,这是升级的直接结果。
解决方案:
将基于
Query<T>
的代码转换为 QueryMultiple
实现。
我根本无法重现这个:
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 或 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(); }
);
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);
QueryMultipleAsync
和
QueryAsync
调用存储过程时遇到同样的问题(以相反的顺序工作!)。我用一个可怕的解决方法解决了:使用 QueryMultipleAsync
时,我在存储过程名称的末尾添加了一个空格。 像这样:
sql += " ";
var gridReader = await connection.QueryMultipleAsync(sql, param, dbTransaction, commandTimeout, commandType);