私はエンティティフレームワークに新しく、シンプルさを愛していますが、速度にいくらか問題があります。私は怠惰なローディングを間違って使っているかもしれないと思っていますが、その周りに頭を巻きつけるのは苦労します。データモデルレイヤーとビジネスエンティティーレイヤーを分離し、データモデルからビジネスエンティティーを作成する関数を使用します。この関数では、異なるネストされたエンティティを反復して、対応するモデルを作成します。 [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
:あなたはこのような行でそれを行うことができますあなたの 'FirstOrDefault'が実行される前にメモリが消費され、速度が低下します。 – SynerCoder
そのコードで更新されました..ありがとう! –
Sql Serverはバックエンドリポジトリですか?もしそうなら、Sql Server Profilerを使用して、実際にサーバー上で何が実行されているかを確認します。複数のステートメント(@SynerCoderで提案されたようなもの)がある場合、FirstOrDefaultを実行する前にテーブル全体を具体化するコードを表示しないでください。いずれにしても、実行中のものを見るためにそれを使用します。それが正しいと思われる場合は、クエリの分析(チューニング)を開始し、間違っているように見える場合は、コードを掘り下げてください。 – Igor