6

私の仕事では、LINQ と Dapper を組み合わせて使用​​しています。パフォーマンス上の理由から、LINQ コードを Dapper に置き換えています。SQL Server から Visual Studio データベース ダイアグラムにドラッグ アンド ドロップして作成した LINQ データ オブジェクトが多数あります。

次の例では、既にメモリ内に LINQ オブジェクトがあり、それをクエリのパラメーターとして Dapper に渡したいと考えています。例えば:

Animal animal = con.Query<Animal>(" select * " +
        " from animal " +
        " where animalid = @AnimalId " +
        " and animaltype = @AnimalType ",
        cagedAnimal).SingleOrDefault();

cagedAnimal には、getter と setter を持つパブリック プロパティ AnimalId と AnimalType が含まれています。

ただし、このコードを実行すると、次のエラーが発生します。

タイプ: SMDApp.Models.Animal は dapper ではサポートされていません

次のコードは機能します。

Animal animal = con.Query<Animal>(" select * " +
            " from animal " +
            " where animalid = @AnimalId " +
            " and animaltype = @AnimalType ",
            new 
            { 
            AnimalId = cagedAnimal.AnimalId, 
            AnimalType = cagedAnimal.AnimalType 
            }
            ).SingleOrDefault();

特にオブジェクトの複数のプロパティをクエリのパラメーターとして使用している場合は、既存のオブジェクトを使用する方が便利です。これが匿名オブジェクトでは機能するが、自動生成された LINQ オブジェクトでは機能しない理由を誰か教えてもらえますか?

Ben Robinson の返信に応じて編集。

Marc Gravell の返信に応じて 2 回目の編集を行いました。

4

2 に答える 2

4

短いバージョンは、すでに動作するはずです。エラーに基づいて:

タイプ: SMDApp.Models.CagedAnimal は dapper ではサポートされていません

new {cagedAnimal}私は、あなたが実際に の代わりにcagedAnimalを渡している、それ自体CagedAnimalが であるプロパティ ( Parent、おそらく?) を持っていてCagedAnimal、どの dapper が理解できないかのいずれかであると結論付けています。現在の動作では、指定されたパラメーター オブジェクトのパブリック プロパティごとにパラメーターが追加されます。プロパティのいずれかをデータベースに送信する方法がわからない場合は、エラーが発生します。値メンバーだけの単純な POCO が正常に機能することがわかるはずです。

でも!SQL を解析しようとしないことに注意してください。特に、提供されたクエリのパラメーターをチェックしません。そのため、POCO アプローチを使用すると、不要なプロパティをクエリに追加することになります。

私たちは dapper を広く使用しており、次のアプローチを使用しています。

 new { obj.Foo, obj.Bar, id, key = "something else" }
于 2011-06-29T12:10:31.840 に答える
3

マークは、特にこの問題を修正するための変更をコミットしました:

  1. プロパティをパラメーターに変換しようとして送信する前に、簡単な検証を実行します。たとえば、この場合、Dapper はサーバーにパラメータを送信しません: cnn.Query("select 1", new {bla = 1}) 原因 "bla" は文字列に存在しません。ストアド プロシージャの場合、この検証はスキップされます。

  2. やや不可解なエラーが修正され、大幅に改善されました。

--

Dapper は、基になる SQL ステートメントの解析を実行していませんでした。たとえば、次のようになります。

@"select * 
from animal
where animalid = @AnimalId"

という単一のパラメータが含まれています@AnimalId

複雑な原因になります。100% 正しくするには、エッジ ケースを処理する必要があります。たとえば@AnimalId、文字列にselect '@AnimalId' -- @AnimalId \* @AnimalId *\? 正規表現は少しトリッキーになります。すべてのエッジケースを考えたわけではありません。例: Oracle は、そのパラメーターの前に a:を付けますが、これは事態をさらに複雑にします。

dapper は文字列内のパラメーターについて何も知らなかったので、すべてのパブリック プロパティをパラメーターとして送信することにしました。一部のパブリック プロパティはマッピングできないDbParametersため、不平を言いました。

于 2011-06-29T12:11:02.683 に答える