从控制器查询列表< >从存储库中获得的增加耦合

本文关键字:耦合 增加 存储 查询 控制器 列表 | 更新日期: 2023-09-27 17:49:52

我有一个ASP。. NET MVC应用程序,用c#编码。应用程序的结构如下:

    控制器
  1. LINQ to Entities (Entity Framework)

  2. 视图

我使用Repository (_ProductRep)来查询LINQ to Entities,并向Controller提供实际实体或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>而不是IQueriable<T>。如果我错了,请纠正我,但我猜,由于列表不需要访问EF DataContext,控制器和EF之间没有耦合。

如果我错了,我能想到的唯一解决方案是用Repository方法代替查询(我仍然必须实现):

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

在此解决方案中,存储库每个循环周期生成一个包含4个条件的查询,而在之前的解决方案中,存储库只生成一个条件的查询。

你能在这个问题上给我一些启发吗?谢谢。

PS:我需要两个变量lproduct_monthlyReportlproductItem_monthlyReport在循环中,我不能只使用其中一个

PPS:我知道我应该在控制器和存储库之间有一个业务服务层,这是我的下一步。

从控制器查询列表< >从存储库中获得的增加耦合

从存储库返回列表将给您带来糟糕的性能,因为您失去了延迟执行行为。基本上,您的存储库将检索每一条记录(而不是相关实体)到内存中,并将它们转换为List,然后在内存中进行处理。如果要访问相关实体,则需要另一个数据库。如果你坚持使用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);

第一个将在没有WHERE子句的数据库中执行SELECT,然后为每个结果实例化. net对象,然后查询内存中的列表。第二个函数在访问product1上的一个属性之前什么都不做,并且此时会发出一个数据库命令来检索1个产品,并且只实例化这1个产品。

对于小数据集,两者之间的差异可能不明显,但随着数据集越来越大,这种差异会越来越严重。加入一个连接的实体(或者更糟的是实体集合),您可能会获得数千个数据库命中,如果您坚持使用IEnumerable,您将获得1个。

我可能会有这样的功能GetArchiveReport(int prodID, int lmonth, int lyear, IEnumerable<int> itemIDs),将做itemid . 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
}