EF(实体框架)中“using”语句的用法

32

我有一个MVC项目。我们选择了EF来进行数据库交互。我们为BLL层创建了一些管理器。我发现很多示例中都使用了"using"语句,例如:

public Item GetItem(long itemId)
    {
        using (var db = new MyEntities())
        {
            return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
        }
    }

在这里,我们创建了一个 DBcontext 的新实例 MyEntities()。 我们使用 "using" 来"确保正确使用 IDisposable 对象。" 我的管理器中只有一个方法。但我有十个以上的方法。 每次调用管理器中的任何方法时,我都会使用 "using" 语句并在内存中创建另一个 DBcontext。垃圾回收器(GC)何时处置它们?有人知道吗?
但是,还有一种管理器方法的替代用法。 我们创建一个全局变量:
private readonly MyEntities db = new MyEntities();

在每个方法中都使用DBcontext,而不需要“using”语句。方法看起来像这样:

public Item GetItem(long itemId)
{
    return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
}

问题:

  1. 使用DBcontext变量的正确方式是什么?
  2. 如果我们不使用"usage"语句(因为它会影响性能)- GC会自动处理吗?

我是EF使用方面的"菜鸟",还没有找到这个问题的明确答案。


取决于你想要达到什么程度。理想情况下,你不应该在控制器中实例化它,而是通过注入(IoC/DI)的方式,这样调用控制器的任何东西(工厂)都可以确定上下文的生命周期。 - Belogix
为什么会影响性能?你有进行过测量,并得出了你正在失去性能的结论吗?而且GC没有处理它,因为你正在使用using语句自己处理它。 - Maarten
2个回答

16

我认为很多人都建议使用这种模式,不只是我或Henk。

DBContext处理

  • 是的,理想情况下应该使用DBContext子类型的Using语句。
  • 更好的方法是,使用Unit Of Work模式,并使用Using进行管理,拥有一个上下文并且在完成之后释放上下文。这里是Tom Dykstra提供的众多UoW示例之一
  • 每个Http请求应该新建一个Unit Of Work Manager。
  • 上下文不是线程安全的,所以请确保每个线程都有自己的上下文。
  • 让EF在后台缓存信息。
  • 测试多次Http请求后上下文创建的时间。是否还存在问题?
  • 如果将上下文存储在静态变量中,则会出现问题。任何并发访问都会受到影响。如果使用并行的AJAX调用,则假设使用静态单个上下文存在90%以上的问题。

这里有一些性能提示,值得一读


1
顺便说一下,“仅是许多UoW示例之一,这个来自Julie Lerman”的是Tom Dykstra写的,不是Julie Lerman。 - Paul Zahra
那么,通过创建新的数据库上下文对象,并使用“using”进行处理,性能比重复使用同一对象更好? - Andrew
没有使用using并不意味着性能更好,如果它可以防止内存泄漏,那么它可能会提高性能。但关键是为了稳定性而这样做。你可以避免问题。 - phil soady

4
使用DBContext变量的适当或最佳实践方式是使用Using语句。
    using (var db = new MyEntities())
    {
        return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
    }

好处在于许多事情都可以自动完成。例如,一旦代码块完成,就会调用dispose。

根据MSDN EF使用DbContext

当实例被创建时,上下文的生命周期开始,并在实例被处理或垃圾回收时结束。如果您希望上下文控制的所有资源在块的末尾被处理,请使用using。当使用using时,编译器会自动创建try/finally块并在finally块中调用dispose。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接