【问题标题】:Why does Dapper QueryAsync<T> behave differently from Query<T> with sproc return values?为什么 Dapper QueryAsync<T> 的行为与带有 sproc 返回值的 Query<T> 不同?
【发布时间】: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


【解决方案1】:

目前 Dapper 不支持不执行 SELECT 语句的异步方法。
Github 中有一个未解决的问题:
https://github.com/StackExchange/Dapper/issues/591

你现在做的事情是这样的:

ALTER PROCEDURE dbo.ConditionalGet
    @ID INT,
    @Output INT OUTPUT
AS
BEGIN

    -- this is a silly made up condition just to test the issue
    IF @ID % 2 = 1
    BEGIN
        SET @Output = -1
    END
    ELSE BEGIN
        SET @Output = 0
    END

    SELECT *
    FROM MyTable
    WHERE ID = @ID
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 2019-06-22
    • 2018-11-05
    • 2014-09-09
    • 2016-11-10
    • 2015-09-22
    • 1970-01-01
    相关资源
    最近更新 更多