9

この質問の詳細が不足していることをお詫びします。最初に助けが必要なのは、詳細を見つけるためにどこを見ればよいかを知ることです。

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);
            }
        }
    }
4

3 に答える 3

1

これは挿入であるため、値を選択し直してオブジェクトを再設定することにより、オブジェクトを更新します。それでは、あなたが提示した質問に答えましょう。

  1. の代わりにデバッグする必要はないはずですSaveChanges()

  2. 実際にはselect * from Receipts. を行っていselect * from Receipts where WarehouseId = 1ます。したがって、何らかの理由で、ID が 1 の倉庫のすべての領収書を取得することを拒否します。

  3. これは非常に多くのことに依存する可能性があるため、今は実際には入り込めません。しかし、まず始めに、アプリ ボックスとデータベース ボックスの間の ping レートを確認してください。また、db ボックスの RAM がいっぱいになっていないことも確認してください。それが私が始めるところです、そしてそれはあなたが説明していることの通常の問題です.

EF をデバッグするための優れたツールは、EF プロファイラーです。 http://efprof.com これは、SQL プロファイラーよりもはるかに役立ちます。

于 2011-04-05T00:23:19.317 に答える
1

問題は、「倉庫」エンティティの「ナビゲーション プロパティ」です。このナビゲーション プロパティを削除します。リレーションシップは引き続き存在しますが、領収書エンティティを作成するときに、その倉庫のすべての領収書をクエリするわけではありません。私は同じ問題を抱えていましたが、これで問題が解決しました。

于 2011-05-13T14:18:02.080 に答える
0

遅延読み込みがオンになっていませんか? その場合、関連するナビゲーション プロパティにアクセスすると、WarehouseDetailsおよびテーブルのクエリが起動されます。Receipts意図せずにクエリを起動しないように、常に遅延読み込みがオフになっていることを確認します。

于 2011-05-13T14:45:10.820 に答える