OracleでDapper QueryMultipleを使用する

dapper oracle

質問

私はOracle(ODP.NET)でdapperを使用しようとしており、 "QueryMultiple"機能を使用したいと考えています。

この文字列をQueryMultipleメソッドに渡す:

 var query = "Select CUST_ID CustId from Customer_info WHERE CUST_ID=:custId;" +
                   "Select CUST_ID CustId from BCR WHERE CUST_ID=:custId";

私はORA-00911を取得しています:無効な文字エラー

これを行う方法はありますか、それは可能ではありませんか?

Tks

人気のある回答

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

DapperはSQLコマンドを直接ADO.NETに渡し、どんなdbプロバイダがコマンドを実行しているようにも見える。各コマンドが改行で区切られている例の構文では、SQL Serverはそれをデータベースに対して実行する複数のクエリとして解釈し、各クエリを実行して結果を別々の出力に返します。私は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コレクションを使用してコマンドのパラメータを指定する必要があります。しわを追加するには、Dapperの通常のDynamicParameters.Add()メソッドで、オプションのdbTypeパラメータにSystem.Data.DbTypeを使用しますが、クエリのカーソルパラメータはOracle.ManagedDataAccess.Client.OracleDbType.RefCursor型にする必要があります。 。これを解決するために、@ Daniel Smithがこの回答で提案したソリューションを使用し、 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();
}


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow