我想知道在使用网站的上下文类连接到db时,性能和一般最佳做法的差异是什么。 考虑这两种不同的方法时,最好的方法是什么:
public class Repository()
{
Private Context context;
public List<User> GetUsers()
{
return this.context.Users.ToList();
}
或
public class Repository()
{
public List<User> GetUsers()
{
using (Context context = new context())
{
return context.Users.ToList();
}
}
}
如果将结果作为List
或IEnumerable
返回,是否重要?
答案 0 :(得分:5)
从MSDN
复制寿命
上下文的生命周期在创建实例时开始,在实例处理或垃圾收集时结束。如果您希望将上下文控制的所有资源放置在块的末尾,请使用。使用时,编译器会自动创建一个try / finally块,并在finally块中调用dispose。
using (var context = new ProductContext())
{
// Perform data access using the context
}
在决定上下文的生命周期时,以下是一些一般性指导原则:
使用长时间运行的上下文时,请考虑以下事项: 当您将更多对象及其引用加载到内存中时,上下文的内存消耗可能会迅速增加。这可能会导致性能问题。 请记住在不再需要时处理上下文。 如果异常导致上下文处于不可恢复状态,则整个应用程序可能会终止。 随着查询和更新数据的时间之间的差距的增大,遇到并发相关问题的可能性也会增加。 使用Web应用程序时,请按请求使用上下文实例。 使用Windows Presentation Foundation(WPF)或Windows窗体时,请为每个窗体使用上下文实例。这使您可以使用上下文提供的更改跟踪功能。
答案 1 :(得分:3)
虽然你已经接受了一个(完全可以接受的)解决生命问题的答案,但我认为最重要的方面只是在克里斯的答案中被撇去。 (IMHO)它应该是选项1的最重要原因是可组合性。 (但一个重要的假设是,在选项1中,存储库在其构造函数中接收上下文,因此在一个用例中可以由多个存储库共享此上下文。)
假设您想在一个查询中加入两个实体:
from u in repo1.GetUsers()
join r in repo2.GetRoles() on u.UserId equals r.UserId
where u.UserId = ...
使用选项2,这将对用户和角色执行单独的查询,因为来自不同上下文的两个DbSet
只能在内存中组合。使用选项1(和一些修改),这将使用SQL连接触发一个组合查询。
您还需要做的事情是返回IQueryable
而不是List
,即返回context.Users
。
此外,使用选项2,如果您对来自不同存储库的实体进行更改,则在一个事务中提交它们会更加精细。 (您需要在每个上下文中调用SaveChanges()
个调用,包含在TransactionScope
)中。
有点偏离主题,但过于相关而忽略的事实是修改后的选项1可能会让你在DbSet
和你的应用程序代码之间留下一个非常非常薄的中间人。您可能会认为此存储库层没有添加任何有用的内容并完全抛弃它。
答案 2 :(得分:1)
绝对是第二种方法。
构建DbContext
几乎是一种无操作。昂贵的事情是创建(而不是建立)与Db的连接,由于连接池,这只发生一次。另一方面,保持连接打开较长时间是一个坏主意(除此之外,它是非常耗费资源的)并且可能导致各种其他问题(例如,由于网络错误导致的连接中断)。
答案 3 :(得分:0)
使用第一个版本。如果需要在存储库中调用多个方法,则只需初始化一次上下文,而不是在每个方法中反复初始化它。此外,通过使用支持字段,您还可以选择利用依赖注入,这是一个强大的概念,可以使您的应用程序分离,灵活,可测试和可维护:
http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection