实体框架和连接池

我最近开始在我的。net 4.0应用程序中使用实体框架4.0,我对一些与池相关的事情很好奇。

  1. 据我所知,连接池由ADO管理。NET数据提供程序,在我的情况下,MS SQL server。当你实例化一个新的实体上下文(ObjectContext),即无参数的new MyDatabaseModelEntities()时,这是否适用?

  2. a)为应用程序创建一个全局实体上下文(即一个静态实例)或b)为每个给定的操作/方法创建并公开一个实体上下文,使用using块,优点和缺点是什么?

  3. 对于我应该知道的某些场景,还有其他建议、最佳实践或常见方法吗?

141619 次浏览

丹尼尔·西蒙斯表示:

中创建一个新的ObjectContext实例 每个服务的Using语句 方法,以便对其进行处理 在方法返回之前。 这一步对于服务的可伸缩性至关重要。它确保数据库连接不会在服务调用之间保持打开状态,并且特定操作使用的临时状态在该操作结束时被垃圾收集。实体框架自动在应用域和ADO中缓存元数据和其他需要的信息。因此,每次重新创建上下文都是一个快速的操作

这是他的一篇综合文章:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

我相信这个建议可以扩展到HTTP请求,所以对ASP.NET也是有效的。有状态的胖客户端应用程序(例如WPF应用程序)可能是“共享”上下文的唯一情况。

  1. 连接池的处理与任何其他ADO一样。网络应用程序。实体连接仍然使用传统的数据库连接和传统的连接字符串。我相信你可以关闭连接字符串中的连接池,如果你不想使用它。(阅读更多关于SQL Server连接池(ADO.NET)的内容)
  2. 永远不要使用全局上下文。ObjectContext内部实现了几个模式,包括标识映射和工作单元。使用全局上下文的影响因应用程序类型而异。
  3. 对于web应用程序,每个请求使用单个上下文。对于web服务,每个调用使用单个上下文。在WinForms或WPF应用程序中,每个表单或每个呈现者使用单个上下文。可能有一些特殊的要求,不允许使用这种方法,但在大多数情况下,这就足够了。

如果你想知道单对象上下文对WPF / WinForm应用程序有什么影响,检查这个文章。它是关于NHibernate会话,但思想是一样的。

编辑:

当您使用EF时,默认情况下每个上下文只加载一次每个实体。第一个查询创建实体实例并在内部存储它。任何需要具有相同键的实体的后续查询都会返回此存储实例。如果数据存储中的值发生了变化,您仍然会收到初始查询中值的实体。这被称为标识映射模式。您可以强制对象上下文重新加载实体,但它将重新加载单个共享实例。

对实体所做的任何更改都不会被持久化,直到对上下文调用SaveChanges。您可以在多个实体中进行更改并一次性存储它们。这被称为工作单元模式。您不能有选择地说要保存哪个已修改的附加实体。

结合这两种模式,您将看到一些有趣的效果。整个应用程序只有一个实体实例。对实体的任何更改都会影响整个应用程序,即使这些更改还没有被持久化(提交)。在大多数情况下,这不是你想要的。假设在WPF应用程序中有一个编辑表单。您正在使用实体,并决定取消复杂的编辑(更改值、添加相关实体、删除其他相关实体等)。但是实体已经在共享上下文中被修改了。你会怎么做?提示:我不知道ObjectContext上有任何CancelChanges或UndoChanges。

我认为我们不必讨论服务器场景。在多个HTTP请求或Web服务调用之间简单地共享单个实体会使应用程序毫无用处。任何请求都可以触发SaveChanges并保存来自另一个请求的部分数据,因为你在所有请求之间共享一个工作单元。这还会有另一个问题——上下文和上下文中实体的任何操作或上下文使用的数据库连接都不是线程安全的。

即使对于只读应用程序,全局上下文也不是一个好选择,因为您可能希望每次查询应用程序时都有新的数据。

下面的代码帮助我的对象刷新与新的数据库值。Entry(object).Reload()命令强制对象收回数据库值

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();

根据EF6(4,5也)文档: https://msdn.microsoft.com/en-us/data/hh949853#9 < / p >

9.3每个请求的上下文

实体框架的上下文意味着作为短期实例使用,以提供最优的性能体验。上下文被期望是短寿命的和废弃的,因此已经被实现为非常轻量级的并尽可能重用元数据。在web场景中,重要的是要记住这一点,不要让上下文超过单个请求的持续时间。类似地,在非web场景中,应该根据您对实体框架中不同级别缓存的理解而放弃上下文。一般来说,应该避免在应用程序的整个生命周期中使用上下文实例,以及每个线程使用上下文和静态上下文。