Dapper:过程或函数指定了太多参数
Posted
技术标签:
【中文标题】Dapper:过程或函数指定了太多参数【英文标题】:Dapper: Procedure or function has too many arguments specified 【发布时间】:2014-07-31 21:53:19 【问题描述】:使用 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 project 第 61 和 228 行。
编辑:我发现问题是由两次调用相同的过程引起的,但结果集不同。所以我第一次用 Query 调用它,第二次用 Query 调用它。为什么 Dapper 在这种情况下遇到问题仍然是个谜。
【问题讨论】:
您的代码似乎正确。所以现在正如错误所说,您已经传递了一些在您的 SP 中未定义的额外参数。因此,请检查您配置要传递的参数的代码。 @KrishnrajRana:感谢您的评论。据我所见,我没有传递额外的参数。由于我发现了一些额外的信息,所以我已经编辑了这个问题。 如果您的 SP 返回多个结果,那么您可以使用 QueryMultiple() 的 dapper。与其调用相同的 SP 两次,不如编写 SP 代码,使其在 sp 中执行第一个结果,然后将其用于第二个结果,然后根据您的要求返回这两个结果集。 【参考方案1】:我最近遇到了这个问题,这似乎是由以下原因引起的:
您的存储过程可以返回多个数据集(可能基于 条件参数)。 您正在使用以下方法调用存储过程Query<T>()
而不是 QueryMultiple()
然后映射数据集
通过Read<T>
。
我们最近从旧版本的 Dapper 升级到 v1.4 以支持表变量参数,并且我们开始遇到这种行为是升级的直接结果。
解决方案:
将基于Query<T>
的代码转换为QueryMultiple
实现。
【讨论】:
【参考方案2】:我根本无法重现:
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;
工作正常。 DynamicParameters
上有一个RemoveUnused
属性,位:使用动态参数时,不应该添加。我什至尝试过使用基于模板的构造函数:
parameters = new DynamicParameters(parameters);
但又一次:这很好用。是否有可能您使用的是 非常非常旧 版本的 dapper?你用的是什么版本?
【讨论】:
这似乎是一个非常具体的错误。我使用的是 NuGet 版本,它是 1.27,因为昨天发布了最新版本。我会深入研究一下,看看能不能找到解释。【参考方案3】:我意识到这是一个旧线程。不过,我使用的是最新版本的 Nuget 包 (1.60.6),最近遇到了这个问题。
要重现这一点,您需要一个基于输入参数的存储过程,该过程可以返回 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();
);
【讨论】:
【参考方案4】:最近遇到了这个问题,原因是使用不同的 Dapper 方法两次调用相同的过程。 对同一 SQL 存储过程的第一次调用是通过 .QueryMultiple。使用 .QuerySingleOrDefault 再次使用参数调用相同的过程导致参数为原始问题中提到的 ParameterNames1 和 RemoveUnused。
【讨论】:
【参考方案5】:这个 Dapper 问题是由在 QueryMultiple 之后读取数据集的 Read 方法引起的。 在这种情况下,Dapper 会缓存参数,如果您使用 Dapper Query 方法调用具有相同参数的相同存储过程,它将失败。 要解决此问题,请将 QueryMultiple 方法的调用从如下更改:
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);
【讨论】:
以上是关于Dapper:过程或函数指定了太多参数的主要内容,如果未能解决你的问题,请参考以下文章