沒實際遇到,但接連兩次被問到使用 Dapper 如何從 Ref Cursor 讀取結果,看來上天已強烈暗示我沒 PO 文分享,趕緊補上以免逆天遭譴。
爬文找到的做法都是靠自訂 OracleDynamicParameter 處理 Ref Cursor 對應轉換,循著 Stackoverlow 討論找到一個 Gist 分享的現成版本,將 OracleDynamicParameter.cs 加入專案,便可使用 OracleDynamicParameters 物件 .Add("cursor_name", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output) 宣告 Ref Cursor 接收查詢結果。Ref Cursor 可用於 PL/SQL Script 或 Stored Procedure,記得改用 QueryMultiple().Read() 讀取結果,如果是 Stored Procedure,QueryMultiple() 時需指定 commandType: CommandType.StoredProcedure 參數。
註:上述的 Gist 版 OracleDynamicParameter配合 Dapper 新版使用時,第 163 列需加上第三個參數 false:appender = SqlMapper.CreateParamInfoGenerator(newIdent, false, false);
測試成功!
附上完成範例:
staticvoid Main(string[] args)
{
using (var cn = new OracleConnection(cs))
{
var p = new OracleDynamicParameters();
p.Add("n", 1234, OracleDbType.Decimal);
p.Add("rc",
dbType: OracleDbType.RefCursor,
direction: ParameterDirection.Output);
//使用 T-SQL Script 測試 Ref Cursor
var cmd = @"
declare
begin
open :rc for select :n as n, sysdate as d from dual;
end;";
var m = cn.QueryMultiple(cmd, p);
var data = m.Read();
Console.WriteLine(JsonConvert.SerializeObject(data));
/*
--假設 Stored Procedure 如下
create or replace procedure MyProc(
n NUMBER,
rc OUT SYS_REFCURSOR
)
as
begin
open rc
for select n as N, sysdate as D
from dual;
end;
*/
//Stored Procedure記得指定commandType
m = cn.QueryMultiple("MyProc", p, commandType: CommandType.StoredProcedure);
data = m.Read();
Console.WriteLine(JsonConvert.SerializeObject(data));
}
Console.Read();
}