sql >> データベース >  >> RDS >> Oracle

OracleでのDapperQueryMultipleの使用

    OPはおそらくこの問題を解決してからかなり経ちますが、執筆時点では、この質問の回答は1つだけであり、DapperのQueryMultiple()を使用する問題は実際には解決されていません。 Oracleを使用したメソッド。 @ Kamolas81が正しく述べているように、公式の例の構文を使用すると、実際にORA-00933: SQL command not properly ended エラーメッセージ。 QueryMultiple()の実行方法に関するある種のドキュメントを探していました。 オラクルと一緒でしたが、答えのある場所が実際には1つもなかったことに驚きました。これはかなり一般的な作業だと思いました。 を救うためにここに答えを投稿しようと思いました :)誰かがこれと同じ問題を抱えている場合に備えて、将来誰かが。

    Dapperは、SQLコマンドをADO.NETおよびコマンドを実行しているdbプロバイダーに直接渡すようです。各コマンドが改行で区切られている例の構文では、SQLサーバーはそれをデータベースに対して実行する複数のクエリとして解釈し、各クエリを実行して結果を個別の出力に返します。私はADO.NETの専門家ではないので、用語をめちゃくちゃにしているかもしれませんが、最終的な結果として、Dapperは複数のクエリ出力を取得し、その魔法を働かせます。

    ただし、Oracleは複数のクエリを認識しません。 SQLコマンドの形式が正しくないと見なし、ORA-00933を返します。 メッセージ。解決策は、カーソルを使用して、DynamicParametersコレクションの出力を返すことです。たとえば、SQL Serverのバージョンは次のようになります:

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

    Oracleバージョンのクエリは次のようになります。

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

    SQL Serverに対して実行されるクエリの場合、Dapperはそこからそれを処理できます。ただし、結果セットをカーソルパラメータに返すため、IDynamicParametersを使用する必要があります。 コマンドのパラメーターを指定するコレクション。しわを追加するには、通常のDynamicParameters.Add() DapperのメソッドはオプションのdbTypeパラメーターにSystem.Data.DbTypeを使用しますが、クエリのカーソルパラメーターはタイプOracle.ManagedDataAccess.Client.OracleDbType.RefCursorである必要があります。 。これを解決するために、@DanielSmithがこの回答 で提案したソリューションを使用しました IDynamicParametersのカスタム実装を作成しました インターフェース:

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

    したがって、すべてのコードは次のようになります。

        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. SQL Serverの分離レベル:一連​​の

    2. Spring、DBCP、MySQLとの接続タイムゾーンの設定

    3. SQL Server 2012 ServicePack1および累積的な更新プログラム1

    4. MySQL errnoを与える外部キーを使用したテーブルの作成:150