C# 从控制器查询列表<;T>;从存储库中获取,是否增加耦合?
我有一个用C#编码的ASP.NET MVC应用程序。应用程序的结构如下:C# 从控制器查询列表<;T>;从存储库中获取,是否增加耦合?,c#,entity-framework,asp.net-mvc-3,repository-pattern,loose-coupling,C#,Entity Framework,Asp.net Mvc 3,Repository Pattern,Loose Coupling,我有一个用C#编码的ASP.NET MVC应用程序。应用程序的结构如下: 控制器 存储库 LINQ到实体(实体框架) 看法 我使用存储库(\u ProductRep)查询LINQ to实体,并将实际实体或列表,而不是IQueriables 我想在我有更多疑问的情况下得到一些帮助。我有以下代码: List<Monthly_Report> lproduct_monthlyReport = _ProductRep.GetArchiveReport(product.Prod_ID, lmon
\u ProductRep
)查询LINQ to实体,并将实际实体或列表
,而不是IQueriables
我想在我有更多疑问的情况下得到一些帮助。我有以下代码:
List<Monthly_Report> lproduct_monthlyReport = _ProductRep.GetArchiveReport(product.Prod_ID, lmonth, lyear);
其中litemList
是产品可能拥有的所有项目的列表
我想知道这个解决方案是否明智地增加了耦合(并且违反了规则),或者它是可以接受的,因为我实际上查询的是列表
,而不是IQueriable
。如果我错了,请纠正我,但我猜由于列表不需要访问EF DataContext,所以控制器和EF之间没有耦合
如果我错了,我能想到的唯一解决方案是用存储库方法替换查询(我仍然需要实现):
但是,使用此解决方案时,存储库在每个循环周期中使用4个条件进行一次查询,而在以前的解决方案中,存储库仅使用一个条件进行查询
你能在这个问题上给我一些启发吗?谢谢
PS:我需要循环中的两个变量lproduct\u monthlyReport
和lproductItem\u monthlyReport
,我不能只使用其中一个
PPS:我知道我应该在控制器和存储库之间有一个业务服务层,这是我的下一步。我可能会有这样的函数
getArchiverReport(int-prodID,int-lmonth,int-lyear,IEnumerable-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
}
从存储库返回列表会给您带来糟糕的性能,因为您会丢失延迟执行行为。基本上,您的存储库将把每一条记录(而不是相关的实体)检索到内存中,并将它们转换成一个列表,然后在内存中进行处理。如果您想访问一个相关的实体,它将需要另一个数据库。如果您坚持使用IEnumerable(或IQueryable),那么您将对客户机隐藏实体框架行为的细微差别,但仍然可以获得延迟加载和延迟执行等优点 现在忽略存储库的细节,如果您这样做:
List<Product> products = MyEntities.Products.ToList();
Product product1 = products.Single(p => p.Id = 1);
List products=myenties.products.ToList();
product1=products.Single(p=>p.Id=1);
它的表现将比这糟糕得多:
IEnumerable<Product> products = MyEntities.Products;
Product product1 = products.Single(p => p.Id = 1);
IEnumerable products=MyEntities.products;
product1=products.Single(p=>p.Id=1);
第一个将在没有WHERE子句的数据库中执行SELECT,然后为每个结果实例化.Net对象,然后在内存列表中查询该对象。第二个将不执行任何操作,直到您访问product1上的属性,并在此时发出一个数据库命令以仅检索1产品,并仅实例化该1产品
对于较小的数据集,2之间的差异可能不明显,但随着数据集变大,这将变得越来越糟糕。加入一个连接的实体(或者更糟糕的实体集合),您可能会得到数千个数据库点击,如果您坚持使用IEnumerable,您将得到1。我不同意这一点。我建议从DAL返回列表。例如调用products.Single(p=>p.Id=1);在没有列表的循环中,每次迭代都会导致一个DB调用。@RichardW1001:谢谢你的回答。存储库模式规定存储库只返回实际的实体。然后,你应该有足够的灵活性来理解在哪里可以放松特定的处方。但是,通过返回IQuerable(或IEnumerable),您需要打开LINQtoSQL上下文,而我使用using指令打开数据上下文(仅在指令区域内有效)是的,这将非常可怕。。。但这和我说的正好相反!我的意思是,如果要从存储库返回项目集合,请将其保留为IEnumerable或IQueryable,而不是or列表,以便保持延迟执行。我想指出的一点是,如果您返回一个列表,那么数据库调用已经完成,并且只能在内存中进行优化。但是,如果返回IEnumerable,则可以在进行数据库调用之前向查询中添加更多筛选器,同时保持EF的分离和忽略。如果在DAL函数中(正确)处理了DataContext,则不能将其保留为IEnumerable或IQueryable。另外,我不建议从DAL发送Linq实体,而是使用DTO'sAm I遗漏了一些东西-为什么这么快就要处理上下文?你明白上下文和连接是完全分开的吗?创建一个新的上下文会有相当大的开销?您不应该让他们坐在那里,但您肯定应该让他们坐在那里足够长的时间,以便以最有效的方式正确地检索数据!建议您启动一个快速控制台应用程序,并排使用这两种方法,使用跟踪/探查器查看每种方法的数据库活动-这将比文字解释得更好。谢谢您的回答。但是,这些函数的用途是什么?使用litemList.Select(item=>item.item_ID)实际上可以进行投影。请你更好地解释一下你的解决办法好吗?
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);