实体框架和连接池
我最近开始在我的.NET 4.0应用程序中使用Entity Framework 4.0,并对与池相关的一些事情感到好奇。
据我所知,连接池由ADO.NET数据提供者管理,在我的情况下是MS SQL服务器。 这是否适用于实例化新实体上下文( ObjectContext
)时,即无参数的new MyDatabaseModelEntities()
?
a)为应用程序创建全局实体上下文(即一个静态实例)或b)为每个给定的操作/方法创建和展示一个实体上下文,并使用一个using
块,有哪些优缺点?
任何其他建议,最佳实践或对于某些应该了解的情景的常见方法?
如果您想知道WPF / WinForm应用程序的单个对象上下文有什么影响,请查看本文。 这是关于NHibernate会话,但想法是一样的。
编辑:
在使用EF时,默认情况下每个实体仅为每个上下文加载一次。 第一个查询创建实体实例并将其存储在内部。 后续任何需要具有相同键的实体的查询才会返回此存储的实例。 如果数据存储中的值发生更改,您仍然收到来自初始查询的值的实体。 这被称为标识映射模式 。 您可以强制对象上下文重新加载实体,但它会重新加载单个共享实例。
在对上下文调用SaveChanges
之前,对实体所做的任何更改都不会持久。 您可以在多个实体中进行更改并一次存储它们。 这被称为工作单元模式 。 你不能有选择地说出你想保存哪个修改的附加实体。
结合这两种模式,你会看到一些有趣的效果。 整个应用程序只有一个实体实例。 即使变更尚未持续(提交),实体的任何更改都会影响整个应用程序。 在大多数情况下,这不是你想要的。 假设你在WPF应用程序中有一个编辑表单。 您正在与实体合作,并且您决定取消复杂的编辑(更改值,添加相关实体,删除其他相关实体等)。 但实体已在共享上下文中进行了修改。 你会怎么做? 提示:我不知道ObjectContext
上的任何CancelChanges或UndoChanges。
我认为我们不必讨论服务器场景。 在多个HTTP请求或Web服务调用之间简单共享单个实体会使您的应用程序无用。 任何请求都可以触发SaveChanges
并从其他请求中保存部分数据,因为您在所有请求之间共享单个工作单元。 这也会带来另一个问题 - 上下文和上下文中实体的任何操作或上下文使用的数据库连接都不是线程安全的。
即使对于只读应用程序,全局上下文也不是一个好的选择,因为每次查询应用程序时都可能需要新数据。
据丹尼尔西蒙斯说:
在每个服务方法的Using语句中创建一个新的ObjectContext实例,以便在方法返回之前处理它。 这一步对于您的服务的可扩展性至关重要。 它确保数据库连接不会在服务调用中保持打开状态,并且特定操作使用的临时状态在操作结束时会被垃圾收集。 实体框架会自动缓存它在应用程序域中所需的元数据和其他信息,并且ADO.NET可以池化数据库连接,因此每次重新创建上下文都是快速操作。
这是来自他的全面文章:
http://msdn.microsoft.com/en-us/magazine/ee335715.aspx
我相信这个建议可以扩展到HTTP请求,所以对ASP.NET有效。 有状态的胖客户端应用程序(如WPF应用程序)可能是“共享”上下文的唯一情况。
符合EF6(4,5也)文档:https://msdn.microsoft.com/en-us/data/hh949853#9
9.3每个请求的上下文
实体框架的上下文旨在用作短期实例,以提供最佳的性能体验 。 预计上下文会被短暂丢弃,并且因此被实现为非常轻量级的,并且尽可能地重新利用元数据。 在Web场景中,记住这一点非常重要,并且不得超过单个请求的持续时间。 同样,在非Web场景中,根据您对实体框架中不同级别的缓存的理解,上下文应该丢弃。 一般来说,应该避免在应用程序的整个生命周期中有一个上下文实例,以及每个线程和静态上下文的上下文。
链接地址: http://www.djcxy.com/p/29235.html上一篇: Entity Framework and Connection Pooling
下一篇: How do I view the SQL generated by the Entity Framework?