Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Menggunakan Dapper QueryMultiple di Oracle

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();
    }


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. masukkan ke... pilih ... dengan subquery atau tanpa urutan kolom

  2. Bagaimana cara memformat hanya catatan yang ORA-01843 tidak dibuang?

  3. Rencana eksekusi Oracle saat menggunakan operator LIKE dengan fungsi DETERMINISTIC

  4. LOAD DATA INFILE setara di Oracle

  5. Oracle SQ Mengidentifikasi Saudara melalui saudara kandung