1

C# でコーディングされた ASP.NET MVC アプリケーションがあります。アプリケーションは次のように構成されています。

  1. コントローラ

  2. リポジトリ

  3. エンティティへの LINQ (エンティティ フレームワーク)

  4. 意見

Repository( _ProductRep) を使用して LINQ to Entities にクエリを実行し、Controller に実際のエンティティ or を渡しList<T>ますIQueriables<T>

疑問を抱く以上の状況について、助けていただきたいと思います。次のコードがあります。

List<Monthly_Report> lproduct_monthlyReport = _ProductRep.GetArchiveReport(product.Prod_ID, lmonth, lyear);

これlproduct_monthlyReportを取得したら、foreach 内でクエリを実行し、特定のレコードを取得する必要があります。現在、次のようなソリューションを実装しました。

foreach (var item in litemList)
{    
   var lproductItem_monthlyReport = lproduct_monthlyReport.Single(m => m.Item_ID == item.Item_ID);
   // Other code
} 

litemList製品が持つことができるすべてのアイテムのリストはどこにありますか.

このソリューションがカップリングを賢明に増加させる (そしてDemeter の法則にList<T>違反する) のか、それとも ではなくa を実際にクエリしているので許容できるのかを知りたかったのIQueriable<T>です。間違っている場合は訂正してください。ただし、List は EF DataContext にアクセスする必要がないため、Controller と EF の間に結合はないと思います。

私が間違っている場合、考えられる唯一の解決策は、クエリを Repository メソッドに置き換えることです (まだ実装する必要があります)。

var lproductItem_monthlyReport_ProductRep.GetArchiveReport(product.Prod_ID, lmonth, lyear, item.Item_ID);

ただし、このソリューションでは、リポジトリはループ サイクルごとに 4 つの条件で 1 つのクエリを作成しますが、以前のソリューションでは、リポジトリは 1 つの条件だけでクエリを作成していました。

この問題について教えてください。ありがとう。

PS: 両方の変数が必要でlproduct_monthlyReportlproductItem_monthlyReportループ内では 1 つだけを使用することはできません

PPS: コントローラーとリポジトリの間にビジネス サービス レイヤーを配置する必要があることはわかっています。これが次のステップです。

4

2 に答える 2

2

リポジトリからリストを返すと、実行の遅延動作が失われるため、パフォーマンスが低下します。基本的に、リポジトリは、関連するエンティティではなく、すべてのレコードをメモリに取得し、それらをリストに変換します。リストは、メモリで処理されます。関連するエンティティにアクセスする場合は、別のデータベースヒットが必要になります。IEnumerable(またはIQueryable)を使用する場合は、エンティティフレームワークの動作の微妙な違いをクライアントから隠していますが、遅延読み込みや遅延実行などの利点があります。

これを行う場合、今のところリポジトリの詳細を無視します。

List<Product> products = MyEntities.Products.ToList();

Product product1 = products.Single(p => p.Id = 1);

これよりもはるかにパフォーマンスが低下します。

IEnumerable<Product> products = MyEntities.Products;

Product product1 = products.Single(p => p.Id = 1);

1つ目は、WHERE句を指定せずにデータベースでSELECTを実行し、すべての結果に対して.Netオブジェクトをインスタンス化してから、そのメモリ内リストをクエリします。2つ目は、product1のプロパティにアクセスするまで何も実行せず、その時点でデータベースコマンドを発行して、1つの製品のみを取得し、その1つの製品のみをインスタンス化します。

2つの違いは、小さなデータセットでは目立たない場合がありますが、データセットが大きくなるにつれて、これはますます悪化します。接続されたエンティティ(またはさらに悪いことにエンティティコレクション)を投入すると、数千のデータベースヒットが発生する可能性があります。IEnumerableを使用している場合は1になります。

于 2011-04-13T13:14:23.930 に答える
1

GetArchiveReport(int prodID, int lmonth, int lyear, IEnumerable<int> itemIDs)おそらく、クエリ内で itemIDs.Contains(tbl.ID) を実行するこのような関数があるでしょう

var SelectedReports = _ProductRep.GetArchiveReport(product.Prod_ID, lmonth, lyear, litemList.Select(item => item.Item_ID));
foreach(var prodItem in SelectedReports)
{
  //Do code
}
于 2011-04-13T13:07:01.320 に答える