0

以下に説明する問題に対してEntityFrameworkを使用する良いアプローチを知っている人はいますか?

私は次のリリースで、ログオンしている顧客の注文を表示するためのパフォーマンスの高い方法を考え出すことを試みています。もちろん、ページングは​​、多くのデータが利用可能な場合に常に使用するのに適した手法です。ページング手法を使用せずに回答を確認したいと思います。

ストーリーは次のとおりです。顧客は、orderstatus=PENDINGを取得する注文を出します。いくつかの戦略に応じて、承認を得るためにその注文をチェーンの上位に移動します。ステータスのすべての変更がログに記録されるため、ステータスのトレースを確認でき、ステータスごとに追加のコメント行を表示することもできます。これにより、インターフェイスでこの順序を確認する人に、さらに価値のある情報を提供できます。

したがって、注文は顧客にリンクされます。1つの注文で、OrderStatusHistoryに複数のorderstatusを保存できます。

私のテストシナリオでは、OrderStatusHistoryテーブルにそれぞれ約5つのレコードを持つ100以上の注文がある顧客を使用しています。今のところ、ページングを使用せずにすべての注文を1ページに表示したいと思います。各注文について、最後の関連ステータスと追加のコメントが表示されます(この最後のステータスにある場合は、両方のフィールドがOrderStatusHistoryから取得され、最も高いレコードが表示されます)。指定されたOrderIdのID)。

私が試したシナリオは複数ありますが、私がすでに試したことについて、他の解決策やコメントを期待したいと思います。

  • Ordersを取得するときにInclude()を実行しようとしましたが、それでもデータベースで複数のクエリが起動されます。各注文は、データベースへの追加のクエリをトリガーして、履歴テーブル内のすべての注文ステータスを取得します。したがって、最後の関連するステータスを返すだけでなく、すべてのステータスがここでクエリされ、さらに100の注文に対して100の追加クエリが起動されます。データベースに100000以上の注文がある場合の問題を想像することができます。
  • データベースに2つの計算列がある:LastStatus、LastStatusInformation、およびエンティティモデルを通じて利用可能な列を取得する通常のLinq-Query。このアプローチの問題は、これらの計算列が、計算列などから数式を削除しないと変更できないスカラー関数を使用して決定されるという事実です。

結局、私はSQLとストアドプロシージャに精通していますが、残りのデータレイヤーはEntity Frameworkを使用しているため、パフォーマンスに疑問がある場合でも、可能な限りそれを維持したいと思います。SQLアプローチを使用して、次のように記述します。

WITH cte (RN, OrderId, [Status], Information)
AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY Id DESC), OrderId,    [Status], Information
FROM OrderStatus
)
SELECT o.Id, cte.[Status], cte.Information AS StatusInformation, o.* FROM [Order] o
INNER JOIN cte ON o.Id = cte.OrderId AND cte.RN = 1
WHERE CustomerId = @CustomerId
ORDER BY 1 DESC;

これは、共通テーブル式によって提供されるステータス情報を使用して、顧客のすべての注文を返します。

Entity Frameworkを使用した優れたアプローチを知っている人はいますか?

4

1 に答える 1

3

このようなものはあなたが望むように動作するはずです(1デシベルの呼び出しのみを行います)が、私はそれをテストしませんでした:

var result = from order in context.Orders
             where order.CustomerId == customerId
             let lastStatus = order.OrderStatusHistory.OrderBy(x => x.Id).Last()
             select new
             {
                 //you can return the whole order if you need
                 //Order = order,
                 //or only the information you actually need to display
                 Number = order.Number,
                 Status = lastStatus.Status,
                 ExtraComment = lastStatus.ExtraComment,
             };

Orderこれは、クラスが次のようになっていることを前提としています。

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string Number { get; set; }
    ...
    public ICollection<OrderStatusHistory> OrderStatusHistory { get; set; }
}

Orderクラスにプロパティのようなものがない場合ICollection<OrderStatusHistory> OrderStatusHistoryは、最初に結合を行う必要があります。その場合はお知らせください。回答を編集して、を含めますjoin

于 2012-11-12T16:09:00.710 に答える