この質問の詳細が不足していることをお詫びします。最初に助けが必要なのは、詳細を見つけるためにどこを見ればよいかを知ることです。
enityフレームワーク4のナビゲーションプロパティに問題があり、変更をコミットするときにパフォーマンスが低下するようです。
this.ObjectContext.SaveChanges();
ナビゲーションプロパティの1つ(領収書テーブル)に約8000行が含まれている場合(これは多くないので問題ないはずです)、30秒以上かかります。
SQLプロファイラーを使用しましたが、EFがレシートからselect *を発行し、非常に遅いことがわかります。
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
// full field list cut for brevity
FROM [dbo].[Receipts] AS [Extent1]
WHERE [Extent1].[WarehouseId] = @EntityKeyValue1',
N'@EntityKeyValue1 int',@EntityKeyValue1=1
現時点では、ObjectContext.SaveChanges()が呼び出されたときに、このテーブルからすべての行を選択する必要が ある理由すらわかりません。
このテーブルに1行を挿入する必要がありますが、それは最初にすべてを選択する理由を説明していません-また、その選択に時間がかかる理由も説明していません(同じクエリがクエリマネージャーで1秒未満かかる)
ですから、今の私の質問は、問題がまだ何であるか正確にはわかりませんが、次のとおりです。
- 問題の詳細はどこで/どのように確認できますか?ObjectContext.SaveChanges()にデバッグできないため、その内部で何が起こっているのかわかりません。
- EFが領収書から*を選択しようとするのはなぜですか?
- なんでこんなに遅いの?クエリマネージャにコピーおよび貼り付けされたまったく同じクエリはほぼ瞬時に実行されます
編集:
このメソッドの呼び出しをコメントアウトすることで、遅いのはレシートコードであることを確認しました。
private void AddReceipt(PurchaseInvoice invoice,
PurchaseInvoiceLine invoiceLine)
{
if (invoice != null && invoiceLine != null)
{
Product product = invoiceLine.Product;
if (product != null)
{
Receipt receipt = new Receipt{ foo = bar };
WarehouseDetail detail = new WarehouseDetail{ foo = bar };
receipt.WarehouseDetails.Add(detail);
invoice.Receipts.Add(receipt);
}
}
}
しかし、なぜこれがEFにそのselect*クエリを発行させるのかはまだわかりません。
によって引き起こされる遅延読み込みの問題である可能性があると思いますinvoice.Receipts.Add(receipt)
。その行の前にinvoice.Receiptsが空であり、.AddをReceiptsに追加するには、最初にコレクションをロードする必要があるためです。ただし、invoiceIdで選択する必要があるのに、warehouseId=1で選択する理由は説明されていません。
編集2:
このメソッドのEFコードを直接SQLコマンドに置き換えることで、問題を「修正」しました。これは素晴らしいアイデアではありません。他の点では完全に優れたORMを使用しているときに、SQLをスローするべきではありません。しかし、今のところ、EFがselect*クエリを実行していた理由がまだわかりません
private void AddReceipt(PurchaseInvoice invoice,
PurchaseInvoiceLine invoiceLine)
{
if (invoice != null && invoiceLine != null)
{
Product product = invoiceLine.Product;
if (product != null)
{
Receipt receipt = new Receipt{ foo = bar };
WarehouseDetail detail = new WarehouseDetail{ foo = bar };
int id = SqlHelper.AddWarehouseDetail(detail);
receipt.WarehouseDetailId = id;
SqlHelper.AddReceipt(receipt);
}
}
}