13

私たちはデータベース プロバイダーとして Oracle を使用しており、データ アクセス レイヤーの一部 (維持が難しく、XSD のマージが難しい) を、最下層で Dapper を使用するより健全なリポジトリ ベースのパターンに置き換えることを検討しています。ただし、オラクルで使用すると、多くの問題が発生しました。

  • 名前付きパラメータ: これらは、クエリで使用されるたびに無視されるように見えます。Oracle は、任意の順序でそれらを解釈するようです。SqlMapper は正しい名前のパラメーターを返しますが、Oracle では正しく解釈されません。

  • 変数の「@」命名規則は、Oracle の名前付きパラメーターと互換性がありません。パラメータの前に「:」が表示されることを期待しています

以前にこれに遭遇した人はいますか?回避策はありますか?

4

2 に答える 2

15

IMO、ここでの正しいアプローチは、(受け入れられた回答によると)データベース固有のパラメータープレフィックスを使用することではなく@( SQLサーバーの場合:、オラクルの場合)、プレフィックスをまったく使用しないことです。したがって、最終的には次のようになります。

il.Emit(OpCodes.Ldstr, prop.Name);

(等)

特に、staticプロパティは、 ごとに 1 つのベンダーに制限されるため、好ましくありませんAppDomain

この変更により、Dapper が更新されました。また、動的に検出BindByNameしてそれに応じて設定するようになりました (すべて への参照は必要ありませOracleCommandん)。

于 2011-06-06T12:21:21.777 に答える
6

名前付きパラメーターの問題の解決は、Oracle コマンドが BindByName プロパティを true に設定する必要があるためであることが判明しました。これを解決するには、SqlMapper 自体を微調整する必要がありました。この調整は移植性がないため (特定の Oracle コマンドの型チェックに依存するため)、これは少し厄介ですが、当面のニーズには合っています。この変更には、SetupCommand メソッドの更新が含まれます。接続オブジェクトからコマンドを作成した後、check を入力し、次のようにフラグを設定します (~ln 635):

var cmd = cnn.CreateCommand();
if (cmd is OracleCommand)
{
    ((OracleCommand)cmd).BindByName = true; // Oracle Command Only
}

最後に、パラメーター名の "@" から ":" への問題に対処するために、CreateParamInfoGenerator メソッドを変更しました。静的文字列を追加しました - DefaultParameterCharacter の値を「:」に設定し、ln 530 を次のように変更しました。

il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [c

il.Emit(OpCodes.Ldstr, DefaultParameterCharacter + prop.Name); // stack is now [parameters] [command] [name] (Changed @ to : for oracle)

および ln 546 から:

il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name] (Changed @ to : for oracle)

に:

il.Emit(OpCodes.Ldstr, DefaultParameterCharacter + prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name] (Changed @ to : for oracle)

これにより、Oracleコマンドでdapperが問題なく動作しました

于 2011-06-02T10:06:03.360 に答える