1

我正在尝试使用 Dapper 从插入查询中获取返回值。

这是我尝试使其工作的方法:

// the query with a "returning" statement
// note : I have a trigger that sets the Id to a new value using the generator IF Id is null...
string SQL = "UPDATE OR INSERT INTO \"MyTable\" (\"Id\", \"Name\") " + "VALUES (@Id, @Name) RETURNING \"Id\"";
using (var conn = new FbConnection(MyConnectionString)) {
    var parameters = new DynamicParameters();
    parameters.Add("Id", null, System.Data.DbType.Int32);
    parameters.Add("Name", "newName", System.Data.DbType.String);
    // --- also add the returned parameters
    parameters.Add("retval", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
    // execute the query with Dapper....
    conn.Execute(SQL, parameters);
    // expecting the new ID here but it is ALWAYS null....!!!
    var newId = parameters.Get<object>("retval"); 
}

现在为了确保我的查询没有问题,而不是问题的根源,我用我的实际连接器(在本例中为 Firebird)实现了一个类似的代码,如下所示:

using (var conn = new FbConnection(MyConnectionString)) {
    FbCommand cmd = new FbCommand(SQL, conn);
    cmd.Parameters.Add("Id", null);
    cmd.Parameters.Add("Name", "newName");
    FbParameter pRet = cmd.Parameters.Add("retval", FbDbType.Integer);
    pRet.Direction = ParameterDirection.ReturnValue;
    conn.Open();
    cmd.ExecuteNonQuery();
    // => the new value is NOT null here, it returns the correct id!!
    var newId = Convert.ToInt32(pRet.Value);
    conn.Close();
}

我在 Dapper 代码中的错误是什么?为什么一个版本可以,而另一个版本不行?我读过 Dapper 执行 ExecuteNonQuery() 所以我不认为这是原因。

4

2 回答 2

3

returning子句的作用类似于select,因为它在结果网格中返回数据。因此,您的查询应该作为查询执行。这还具有显着简化调用代码的优点:

var newId = conn.QuerySingle<int>(SQL, new { Id = (int?)null, Name = "newName" });

如果您需要其他字段,可以将其扩展为使用与返回的列匹配的自定义返回类型或值元组。例如:

var row = conn.QuerySingle<MyTable>(SQL, new { Id = (int?)null, Name = "newName" });

或者

var row = conn.QuerySingle<(int id, string name)>(SQL, new { Id = (int?)null, Name = "newName" });

--edit 您可以通过以下方式访问返回的值

int iVal = row.Result.id;
string sVal = row.Result.name; 
于 2020-03-28T16:31:35.470 回答
0

Dapper 的 Execute() 的最大缺点是它返回“受影响的行数”(通过更新、删除等)......即使所有发生在事务中,在发生错误后通过ROLLBACK取消。返回值仍然保留回滚之前的受影响行数,但未提交事务。 哎呀!!

DynamicParameters() 更复杂,但有效。但是在 Moq Tests 中,我遇到了一些我无法轻松解决的异常。

我的解决方案(类似于 Marc 和 neggenbe 的)遵循以下步骤:

  1. 在 SQL 存储过程中,通过返回一个整数值,
SELECT -1    -- 0 for success, -1 for error

note--> SQL-Returns (ie. RETURN(1)) are ignored for some reason.
  1. 像这样使用 Dapper,
int result = conn.QueryFirst<int>(SProcName, new { id = req.Id, value = req.Value }, commandType: CommandType.StoredProcedure);

note--> Other commands work as well with differing return types:
           QueryFirst:       result = key/value where value=[return value]
           QueryFirst<int>:  result = integer
           QuerySingle:      Detailed by Marc and neggenbe's answer.
  1. 适当地检查结果,如上面的例子。
于 2021-02-25T22:25:59.197 回答