8

5 つの個別のテーブルを含む Entity Framework プロジェクトがあります。これらのテーブルからデータをクエリして を使用する.Include()と、生成されるクエリが非常に遅くなり、タイムアウトになります。

クエリをストアド プロシージャに移動しました。現在、このストアド プロシージャをクエリし、返されるデータを既存のデータ クラスに簡単にマップする方法を探しています。

EF の DataContext に対する元の Linq クエリは次のようになりました。

var data = (from a in context.A
                    .Include("B")
                    .Include("C")
                    .Include("D")
                    .Include("E")
            where a.Id == someValue
            select a);

次のような Entity データ オブジェクトを返します。

class A
{
    int Id;
    string otherProperties;

    List<B> B;
    List<C> C;
    List<D> D;
    List<E> E;
}

SQL サーバーで実行するために EF が生成したクエリは、次のような結果セットを返しました。

C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
-------------------------------------------------- --------
A1 A2 B1 B2        
A1 A2 C1 C2
A1 A2 C1 C2
A1 A2 C1 C2
A1 A2 D1 D2
A1 A2 D1 D2
A1 A2 D1 D2
A1 A2 E1 E2
A1 A2 E1 E2

(1 B レコード、3 C レコード、3 D レコード、および 2 E レコードを想定しています。

このクエリをストアド プロシージャで再現し、実行時間を実質的にゼロに短縮しましたが、結果セットを Entity Framework データ クラス (上記のクラス) にマップする方法を見つけようとしていますA

EF は、Linq クエリを使用するときにすでに舞台裏のどこかでそれを行っているため、これが確実に可能ですが、それが私がアクセスできるものであるかどうかはわかりません。

Entity Framework で単一のストアド プロシージャ (Function Import) を複数レベルの Entity Framework クラスにマップする簡単な方法はありますか?

4

3 に答える 3

2

EntityFrameworkでこれを行う方法を説明するブログ投稿を見つけました。

http://blogs.infosupport.com/ado-net-entity-framework-advanced-scenarios-working-with-stored-procedures-that-return-multiple-resultsets/

簡単にまとめると、Entity Frameworkで期待される特定の方法でデータを返すようにストアドプロシージャを作成する必要があります。次に、いくつかのEF拡張機能を使用して、ストアドプロシージャの実行をカスタマイズし、オブジェクトグラフを具体化できます。

これは将来のバージョン(5.0以降)でEntity Frameworkに組み込まれているようですが、この回避策は下位バージョンでも機能するようです。

私の場合、.Include()Linqクエリでを削除し、オブジェクトを返す前にコードで他のプロパティを参照して手動で他のプロパティの読み込みをトリガーすると、パフォーマンスの問題が修正されました。これは、最適化されていない結合を使用して5つのテーブル間で1つの大規模なクエリを作成する代わりに、それぞれが必要な特定のデータのみを取得する5つの個別のクエリを実行するためです。

于 2013-01-18T15:27:28.630 に答える
1

高価なクエリをストアド プロシージャに変換して EntityFramework を最適化する場合、結果のカスタム クラスを作成し、DbContext でいくつかのロジックを実行して、カスタム クラスをエンティティに変換します。

したがって、次のようなものを作成します

public class StoreProcARow
{
public string Name {get;set;} // properties for every column
}

そして、あなたのDbContext

public A GetA(int ID)
{
// do stored procedure
IEnumerable<StoreProcARow> procResult = ...
// process procResult into A type

}
于 2013-01-17T18:02:43.893 に答える
0

AutoMapperを試してください。

次のようにします。

using AutoMapper;

...

Mapper.CreateMap<DataModel.B, ReplyObjects.B>;
Mapper.CreateMap<DataModel.C, ReplyObjects.C>;
...
return new A
{
  B = Mapper.Map<DataModel.B, ReplyObjects.B>(varContainingDataForB),
  C = Mapper.Map<DataModel.C, ReplyObjects.C>(varContainingDataForC)
  ...
};

ReplyObjects.B のプロパティが DataModel.B の名前と型と一致している限り、すべてが自動的にマップされます。

于 2013-01-17T18:11:49.633 に答える