从控制器查询列表< >从存储库中获得的增加耦合
本文关键字:耦合 增加 存储 查询 控制器 列表 | 更新日期: 2023-09-27 17:49:52
我有一个ASP。. NET MVC应用程序,用c#编码。应用程序的结构如下:
- 控制器
- 库
LINQ to Entities (Entity Framework)
视图
我使用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_monthlyReport
和lproductItem_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
}