2016-06-28 4 views
3

私はエンティティフレームワークに新しく、シンプルさを愛していますが、速度にいくらか問題があります。私は怠惰なローディングを間違って使っているかもしれないと思っていますが、その周りに頭を巻きつけるのは苦労します。データモデルレイヤーとビジネスエンティティーレイヤーを分離し、データモデルからビジネスエンティティーを作成する関数を使用します。この関数では、異なるネストされたエンティティを反復して、対応するモデルを作成します。 [OK]を、ここでの十分なとりとめはいくつかのコードです:Entity Frameworkのクエリが遅すぎる

IM_ITEM.cs(製品データモデル)

public partial class IM_ITEM 
{ 
    public IM_ITEM() 
    { 
     this.IM_INV = new HashSet<IM_INV>(); 
     this.IM_BARCOD = new HashSet<IM_BARCOD>(); 
     this.IM_GRID_DIM_1 = new HashSet<IM_GRID_DIM_1>(); 
     this.IM_GRID_DIM_2 = new HashSet<IM_GRID_DIM_2>(); 
     this.IM_GRID_DIM_3 = new HashSet<IM_GRID_DIM_3>(); 
     this.IM_PRC = new HashSet<IM_PRC>(); 
    } 

    public string ITEM_NO { get; set; } 
    public string DESCR { get; set; } 
    // many more properties... 

    public virtual ICollection<IM_INV> IM_INV { get; set; } 
    public virtual ICollection<IM_BARCOD> IM_BARCOD { get; set; } 
    public virtual ICollection<IM_GRID_DIM_1> IM_GRID_DIM_1 { get; set; } 
    public virtual ICollection<IM_GRID_DIM_2> IM_GRID_DIM_2 { get; set; } 
    public virtual ICollection<IM_GRID_DIM_3> IM_GRID_DIM_3 { get; set; } 
    public virtual ICollection<IM_PRC> IM_PRC { get; set; } 
} 

ビジネスエンティティの作成方法:

public static ProductEntity FromEfObject(IM_ITEM obj) { 
    var product = new ProductEntity { 
     ItemNumber = obj.ITEM_NO, 
     StyleNumber = obj.VEND_ITEM_NO, 
     Title = obj.DESCR_UPR, 
     LongName = obj.ADDL_DESCR_1, 
     ShortDescription = obj.DESCR, 
     VendorCode = obj.ITEM_VEND_NO, 
     Quarter = obj.ATTR_COD_2, 
     Color = obj.PROF_ALPHA_2, 
     Markdown = obj.PRC_1, 
     Price = obj.REG_PRC ?? 0, 
     Status = obj.STAT, 
     DepartmentCode = obj.ATTR_COD_1, 
     DepartmentDigit = obj.ATTR_COD_1.Substring(0, 1), 
     MixAndMatch = obj.MIX_MATCH_COD, 
     Inventory = new Inventory(obj.IM_INV), 
     Sizes = new List<ProductSize>(), 
     Widths = new List<ProductSize>(), 
     Lengths = new List<ProductSize>(), 
     Barcodes = new Dictionary<string, string>() 
    }; 


    if (obj.IM_PRC.Any()) { 
     var price = obj.IM_PRC.First(); 
     product.DnsPrice2 = price.PRC_2.GetValueOrDefault(); 
     product.DnsPrice3 = price.PRC_3.GetValueOrDefault(); 
    } 

    foreach (var barcode in obj.IM_BARCOD) { 
     product.Barcodes.Add(barcode.DIM_1_UPR, barcode.BARCOD); 
    } 

    foreach (var size in obj.IM_GRID_DIM_1) { 
     product.Sizes.Add(ProductSize.FromEfObject(size)); 
    } 

    foreach (var width in obj.IM_GRID_DIM_2) { 
     product.Widths.Add(ProductSize.FromEfObject(width)); 
    } 

    foreach (var length in obj.IM_GRID_DIM_3) { 
     product.Lengths.Add(ProductSize.FromEfObject(length)); 
    } 

    if (!product.Sizes.Any()) { 
     product.Sizes.Add(new ProductSize()); 
    } 

    if (!product.Widths.Any()) { 
     product.Widths.Add(new ProductSize()); 
    } 

    if (!product.Lengths.Any()) { 
     product.Lengths.Add(new ProductSize()); 
    } 

    return product; 
} 

とモデルを取得するための私の方法:

public ProductEntity GetProductById(string itemNumber, int storeNumber) { 
    var product = _unitOfWork 
     .GetProductRepository(storeNumber) 
     .GetQueryable() 
     .FirstOrDefault(p => p.ITEM_NO == itemNumber); 

    return product == null ? null : ProductEntity.FromEfObject(product); 
} 

GetQueryableメソッド:

internal DbSet<TEntity> DbSet; 
public GenericRepository(TContext context) 
{ 
    Context = context; 
    DbSet = context.Set<TEntity>(); 
} 

public virtual IQueryable<TEntity> GetQueryable() 
{ 
    IQueryable<TEntity> query = DbSet; 
    return query; 
} 

もう少し詳しく..私はデータモデルを作成するためにデータベースの最初のモデリングを使用しましたが、テストしているデータベースには大量のデータがありません。また、私のGetProductByIdの方法で.Include()を使ってみましたが(熱心に私は信じています)、それをさらに減速させました。

私は基本的に何か間違っていますか?または、このようなクエリでEFが遅くなることがあります。

EDIT:、これは私に遅延読み込みを使用するよりも時間がかかるだけで一つの大きな厄介なクエリを与える

public ProductEntity GetProductById(string itemNumber, int storeNumber) { 
     var product = _unitOfWork 
      .GetProductRepository(storeNumber) 
      .GetQueryable() 
      .Include(p => p.IM_INV.Select(i => i.IM_INV_CELL)) 
      .Include(p => p.IM_BARCOD) 
      .Include(p => p.IM_GRID_DIM_1) 
      .Include(p => p.IM_GRID_DIM_2) 
      .Include(p => p.IM_GRID_DIM_3) 
      .Include(p => p.IM_PRC) 
      .FirstOrDefault(p => p.ITEM_NO == itemNumber); 

     return product == null ? null : ProductEntity.FromEfObject(product); 
    } 

トレースhttp://pastebin.com/LT1vTETb

+3

:あなたはこのような行でそれを行うことができますあなたの 'FirstOrDefault'が実行される前にメモリが消費され、速度が低下します。 – SynerCoder

+0

そのコードで更新されました..ありがとう! –

+0

Sql Serverはバックエンドリポジトリですか?もしそうなら、Sql Server Profilerを使用して、実際にサーバー上で何が実行されているかを確認します。複数のステートメント(@SynerCoderで提案されたようなもの)がある場合、FirstOrDefaultを実行する前にテーブル全体を具体化するコードを表示しないでください。いずれにしても、実行中のものを見るためにそれを使用します。それが正しいと思われる場合は、クエリの分析(チューニング)を開始し、間違っているように見える場合は、コードを掘り下げてください。 – Igor

答えて

1

あなたが最適化することができます:遅延ロードを防止するためには、私はに私のクエリを更新します遅延読み込みを避けるためのクエリこの場合、データベースからオブジェクトをロードすると、ほぼオブジェクトグラフ全体をメモリにマップする必要があることがわかります。後でこれらの外部キーをすべて後で検索する必要があります。遅延読み込みを行うのではなく、すべてを1つのクエリとして実行する方が高速です。詳細については、hereを参照してください。

それは次のようなものになります。これらの外部キーはまた、あなたのProductEntityモデルにマップする必要があり、独自の外部キー(すなわちIM_BARCODがIM_OtherTypeのコレクションを持っている)、あなたを持っている場合は、その

public ProductEntity GetProductById(string itemNumber, int storeNumber) { 
    var product = _unitOfWork 
     .GetProductRepository(storeNumber) 
     .GetQueryable() 
     .Include(p => p.IM_BARCOD) 
     .Include(p => p.IM_GRID_DIM_1) 
     .Include(p => p.IM_GRID_DIM_2) 
     .Include(p => p.IM_GRID_DIM_3) 
     .Include(p => p.IM_PRC) 
     .FirstOrDefault(p => p.ITEM_NO == itemNumber); 

    return product == null ? null : ProductEntity.FromEfObject(product); 
} 

注意をそれらも含めるべきです。その部分が間違っている場合、それはEFはにあなたの製品全体のテーブルを照会することが考えられますので、 `)` _unitOfWork.GetProductRepository(storeNumber).GetQueryable(の実装は何

.Include(p => p.IM_BARCOD.Select(b => b.IM_OTHERTYPE)) 
+0

この場合、私はしたいと思います。インクルードする前にどこか(p => p.ITEM_NO == itemNumber)?私はそれをテストしたところ、約8秒から約20秒になりましたので、含まれていないデバッグまで戻りました。 –

+0

いいえ、あなたはどこにいなくてもかまいません。 EFでは、このコードはすべて単一のSQLクエリに変換されます。実際にはC#では実行されません。ステートメントの順序は、最後に同じSQL照会に変わるので問題はありません。 –

+0

それは知っておくといいです..私はそれが1つのクエリにコンパイルされていたことを知っていましたが、それは物事を注文するほどスマートだったのか分からなかった。 –

関連する問題