OP mungkin sudah lama memecahkan masalah sekarang, tetapi pada saat penulisan, pertanyaan ini hanya memiliki satu jawaban dan itu tidak benar-benar menyelesaikan masalah menggunakan QueryMultiple()
Dapper metode dengan Oracle. Seperti yang dinyatakan oleh @Kamolas81 dengan benar, dengan menggunakan sintaks dari contoh resmi, seseorang memang akan mendapatkan ORA-00933: SQL command not properly ended
pesan eror. Saya menghabiskan beberapa saat mencari semacam dokumentasi tentang bagaimana melakukan QueryMultiple()
dengan Oracle, tetapi saya terkejut bahwa tidak ada satu tempat pun yang memiliki jawaban. Saya akan berpikir ini menjadi tugas yang cukup umum. Saya pikir saya akan memposting jawaban di sini untuk menyelamatkan saya :) seseorang beberapa waktu di masa depan kalau-kalau ada yang kebetulan memiliki masalah yang sama.
Dapper tampaknya hanya meneruskan perintah SQL langsung ke ADO.NET dan penyedia db apa pun yang menjalankan perintah. Dalam sintaks dari contoh, di mana setiap perintah dipisahkan oleh jeda baris, SQL server akan menafsirkannya sebagai beberapa kueri untuk dijalankan terhadap database dan itu akan menjalankan setiap kueri dan mengembalikan hasilnya ke output terpisah. Saya bukan ahli ADO.NET, jadi saya mungkin mengacaukan terminologi, tetapi efek akhirnya adalah Dapper mendapatkan beberapa keluaran kueri dan kemudian melakukan keajaibannya.
Oracle, bagaimanapun, tidak mengenali beberapa kueri; ia berpikir bahwa perintah SQL salah format dan mengembalikan ORA-00933
pesan. Solusinya adalah dengan menggunakan kursor dan mengembalikan output dalam koleksi DynamicParameters. Misalnya, sedangkan versi SQL Server akan terlihat seperti ini:
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
versi Oracle dari kueri harus terlihat seperti ini:
var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
"END;";
Untuk kueri yang dijalankan terhadap SQL Server, Dapper dapat menanganinya dari sana. Namun, karena kami mengembalikan kumpulan hasil ke dalam parameter kursor, kami harus menggunakan IDynamicParameters
koleksi untuk menentukan parameter untuk perintah. Untuk menambahkan kerutan ekstra, DynamicParameters.Add()
yang normal metode di Dapper menggunakan System.Data.DbType untuk parameter dbType opsional, tetapi parameter kursor untuk kueri harus bertipe Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor
. Untuk mengatasi ini, saya menggunakan solusi yang diusulkan @Daniel Smith di jawaban ini
dan membuat implementasi kustom IDynamicParameters
antarmuka:
using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;
public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
private readonly DynamicParameters dynamicParameters = new DynamicParameters();
private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction, object value = null, int? size = null)
{
OracleParameter oracleParameter;
if (size.HasValue)
{
oracleParameter = new OracleParameter(name, oracleDbType, size.Value, value, direction);
}
else
{
oracleParameter = new OracleParameter(name, oracleDbType, value, direction);
}
oracleParameters.Add(oracleParameter);
}
public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction)
{
var oracleParameter = new OracleParameter(name, oracleDbType, direction);
oracleParameters.Add(oracleParameter);
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);
var oracleCommand = command as OracleCommand;
if (oracleCommand != null)
{
oracleCommand.Parameters.AddRange(oracleParameters.ToArray());
}
}
}
Jadi semua kode bersama-sama menjadi seperti ini:
using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;
int selectedId = 1;
var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
"END;";
OracleDynamicParameters dynParams = new OracleDynamicParameters();
dynParams.Add(":rslt1", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt2", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt3", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":id", OracleDbType.Int32, ParameterDirection.Input, selectedId);
using (IDbConnection dbConn = new OracleConnection("<conn string here>"))
{
dbConn.Open();
var multi = dbConn.QueryMultiple(sql, param: dynParams);
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
dbConn.Close();
}