【发布时间】:2017-08-30 16:23:26
【问题描述】:
我有一个执行检查并返回一行或非零返回值的存储过程:
CREATE PROCEDURE dbo.ConditionalGet
@ID INT
AS
BEGIN
-- this is a silly made up condition just to test the issue
IF @ID % 2 = 1
BEGIN
RETURN -1
END
SELECT *
FROM MyTable
WHERE ID = @ID
RETURN 0
END
我有一个 C# repo 类,它使用 Dapper 返回结果或抛出异常:
public class Repo
{
public MyClass Get(int id)
{
using (var conn = GetSqlConnection())
{
var p = new { ID = id };
var pWithReturnValue = new DynamicParameters(p);
p.Add("return", null, DbType.Int32, ParameterDirection.ReturnValue);
var result = conn.Query<MyClass>("dbo.ConditionalGet", p, commandType: CommandType.StoredProcedure);
var errorCode = p.Get<int>("return");
if (errorCode != 0)
throw new RepositoryGetException(errorCode);
return result.FirstOrDefault();
}
}
}
这按预期工作:当 id 可被 2 整除时,返回水合对象,否则抛出异常。
但是,当我使代码异步时,这会失败!
public class Repo
{
public async Task<MyClass> Get(int id)
{
using (var conn = GetSqlConnection())
{
var p = new { ID = id };
var pWithReturnValue = new DynamicParameters(p);
p.Add("return", null, DbType.Int32, ParameterDirection.ReturnValue);
// this is the only change!
var result = await conn.QueryAsync<MyClass>("dbo.ConditionalGet", p, commandType: CommandType.StoredProcedure);
var errorCode = p.Get<int>("return");
if (errorCode != 0)
throw new RepositoryGetException(errorCode);
return result.FirstOrDefault();
}
}
}
这会引发 InvalidOperationException “未选择任何列”!
我真的很喜欢这里的模式并且想异步使用它,那为什么会失败呢?我试过关闭和打开缓冲,但没有任何区别。
【问题讨论】:
-
我不知道,但您不应该直接从客户端代码使用存储过程返回值。而是使用错误(throw、raiserror)来指示存储过程中的成功或失败,或者使用 TSQL 批处理中的返回值并在非零返回值上引发错误。
标签: c# sql-server dapper