Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Sử dụng Dapper QueryMultiple trong Oracle

OP có lẽ đã giải quyết được vấn đề này từ lâu, nhưng tính đến thời điểm viết bài, câu hỏi này chỉ có một câu trả lời và nó không thực sự giải quyết được vấn đề khi sử dụng QueryMultiple() của Dapper với Oracle. Như @ Kamolas81 đã tuyên bố chính xác, bằng cách sử dụng cú pháp từ các ví dụ chính thức, người ta sẽ thực sự nhận được ORA-00933: SQL command not properly ended thông báo lỗi. Tôi đã dành một lúc để tìm kiếm một số loại tài liệu về cách thực hiện QueryMultiple() với Oracle, nhưng tôi ngạc nhiên rằng không có một nơi nào thực sự có câu trả lời. Tôi đã nghĩ rằng đây là một nhiệm vụ khá phổ biến. Tôi nghĩ rằng tôi sẽ đăng một câu trả lời ở đây để cứu tôi :) một người nào đó trong tương lai phòng trường hợp có ai đó xảy ra vấn đề tương tự.

Dapper dường như chỉ chuyển thẳng lệnh SQL tới ADO.NET và bất kỳ trình cung cấp db nào đang thực thi lệnh. Trong cú pháp từ các ví dụ, trong đó mỗi lệnh được phân tách bằng dấu ngắt dòng, máy chủ SQL sẽ diễn giải đó là nhiều truy vấn chạy trên cơ sở dữ liệu và nó sẽ chạy từng truy vấn và trả kết quả thành các đầu ra riêng biệt. Tôi không phải là chuyên gia ADO.NET, vì vậy tôi có thể nhầm lẫn thuật ngữ, nhưng kết quả cuối cùng là Dapper nhận được nhiều kết quả truy vấn và sau đó hoạt động kỳ diệu của nó.

Tuy nhiên, Oracle không nhận ra nhiều truy vấn; nó cho rằng lệnh SQL không đúng định dạng và trả về ORA-00933 thông điệp. Giải pháp là sử dụng con trỏ và trả về kết quả đầu ra trong bộ sưu tập DynamicParameters. Ví dụ:trong khi phiên bản SQL Server sẽ giống như sau:

var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

phiên bản Oracle của truy vấn sẽ cần có dạng như sau:

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;";

Đối với các truy vấn chạy trên SQL Server, Dapper có thể xử lý nó từ đó. Tuy nhiên, vì chúng tôi đang trả lại các tập kết quả thành các tham số con trỏ, chúng tôi sẽ cần sử dụng IDynamicParameters tập hợp để chỉ định các tham số cho lệnh. Để thêm nếp nhăn, DynamicParameters.Add() bình thường phương thức trong Dapper sử dụng System.Data.DbType cho tham số dbType tùy chọn, nhưng các tham số con trỏ cho truy vấn cần phải thuộc loại Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor . Để giải quyết vấn đề này, tôi đã sử dụng giải pháp mà @Daniel Smith đã đề xuất trong câu trả lời này và tạo một triển khai tùy chỉnh của IDynamicParameters giao diện:

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

Vì vậy, tất cả các mã kết hợp với nhau sẽ giống như sau:

    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. Cách chèn một chuỗi dài vào kiểu dữ liệu CLOB trong Oracle

  2. Hibernate Jpa - ngoại lệ vi phạm ràng buộc trên Khóa chính (Trình tự)

  3. Chuyển đổi hàng cột trong Oracle Sql

  4. Mối quan hệ Nhiều-Nhiều trong Khung thực thể với thông tin về mối quan hệ

  5. Chuyển phân số thành thập phân