0

エンティティ フレームワーク バージョン 1 によって作成されたエンティティ タイプがあります。それをトランザクションと呼びましょう。次のプロパティを追加しました。

public partial class Transaction
{
    public int CurrentMaxRevisionNumber { get; set; }
}

そして、次のクエリがあります。

public List<Transaction> GetTransactions(DateTime startDate, DateTime endDate)
{
   var query = from t in Repository.Transaction  
       let currentMaxRevisionNumber = 
        Repository.Transaction.Where(t1 => t1.TransactionId == t.TransactionId)
                               .Max(t1 => t.RevisionNumber)
       where t.StartDate >= startDate
             && t.EndDate < endDate)
    select t;

    return query.ToList();
}

私たちが達成しようとしているビジネス ルールは次のとおりです。
- 元の日付のトランザクションの新しいレコードは、リビジョン番号を増やして論理的に削除されたことを示すコードで作成する必要があります。
- トランザクションの新しいレコードは、リビジョン番号を増やして新しい日付に作成されます。

問題は、トランザクションがいつ処理されるかを決定するプロセスが 1 日 1 日順番に実行され、トランザクションが日付から日付へと移動し、時には元のトランザクションに頻繁に戻ることです。これにより、特定のトランザクションの最大リビジョン番号が、トランザクションの最大ではなく、特定の日付からのものになる場合があります。それが、クエリで「let」を実行しようとしている理由です。

ここでの質問:
- 部分クラスで作成した CurrentMaxRevisionNumber プロパティにクエリを設定するにはどうすればよいですか?
- 特定の日付に数百のトランザクションが発生する可能性があるため、トランザクションごとにクエリを実行することなくこれを達成できる別の方法はありますか?

助けてくれてありがとう。

4

1 に答える 1

0

そこで私が最初に試したのは、アンチパターンの SELECT n + 1 を使用することでした。これは恐ろしい解決策ですが、少なくとも、正しいデータを取得することで問題が解決されることがわかりました。それは次のようなものでした:

public List<Transaction> GetTransactions(DateTime startDate, DateTime endDate)
{
   var list = (from t in Repository.Transaction  
       where t.StartDate >= startDate
             && t.EndDate < endDate)
    select t).ToList();

    foreach(var item in list)
    {
        item.CurrentMaxRevisionNumber = Repository.Transaction.
                                        Where(t => t.TransactionId == item.TransactionId).
                                        Max(t => t.RevisionNumber);
    }

    return list;
}

明らかな理由から、この解決策は受け入れられなかったため、次のように考えました。

public List<Transaction> GetTransactions(DateTime startDate, DateTime endDate)
{
   var query = (from t in Repository.Transaction       
       where t.StartDate >= startDate
             && t.EndDate < endDate)
    select new
    {
       OriginalTransaction = t,
       CurrentMaxRevisionNumber = Repository.Transaction.
                                        Where(t1 => t1.TransactionId == t.TransactionId).
                                        Max(t1 => t1.RevisionNumber);
    }).ToList();

    foreach(var item in list)
    {
       item.OriginalTransaction.CurrentMaxRevisionNumber = item.CurrentMaxRevisionNumber;
    }

    return list.Select(items => items.OriginalTransaction).ToList();
}

匿名オブジェクトを使用することで、1 回のデータベース アクセスで必要なすべてのデータを取得し、ループを使用して不足しているプロパティを設定できます。

データベースを変更する必要があり、アプリケーションが多少制限されていたため、このソリューションが最も侵襲性が低く、パフォーマンスが高いことが証明されました。

于 2012-11-06T16:20:20.237 に答える