Entity Framework和连接池化
Entity Framework和连接池化
我最近在我的.NET 4.0应用程序中开始使用Entity Framework 4.0,并且对与连接池相关的一些事情感到好奇。
- 据我所知,连接池是由ADO.NET数据提供程序管理的,在我的情况下是MS SQL Server。当您实例化一个新的实体上下文(ObjectContext),即无参数的new MyDatabaseModelEntities()时,是否适用于此?
- 全局entities上下文的创建方法有哪些优点和缺点,比如创建应用程序的静态实例,或者为每个操作/方法创建和公开一个entities上下文,并使用
using
块。 - 还有其他建议、最佳实践或特定场景下常用的方法吗?
- 连接池的处理方式与其他ADO.NET应用程序相同。实体连接仍然使用传统的数据库连接和传统的连接字符串。如果您不想使用它,我相信您可以在连接字符串中关闭连接池。(阅读有关SQL Server连接池(ADO.NET)的更多信息)
- 永远不要使用全局上下文。对象上下文内部实现了几个模式,包括Identity Map和Unit of Work。使用全局上下文的影响不同于应用程序类型。
- 对于Web应用程序,每个请求使用一个单一的上下文。对于Web服务,每个调用使用一个单一的上下文。在WinForms或WPF应用程序中,每个窗体或每个Presenter使用一个单一的上下文。可能会有一些特殊的要求,不允许使用这种方法,但在大多数情况下这已经足够了。
如果您想知道单个对象上下文对WPF / WinForm应用程序的影响,请查看此文章。它是关于NHibernate Session的,但其思想是相同的。
编辑:
当您使用EF时,默认情况下每个上下文仅加载实体一次。第一个查询创建实体实例并在内部存储它。任何需要具有相同键的实体的后续查询都会返回此存储的实例。如果数据存储中的值已更改,则仍会收到来自初始查询的具有值的实体。这称为Identity map pattern。您可以强制对象上下文重新加载实体,但它将重新加载单个共享实例。
对实体所做的任何更改在调用上下文上的SaveChanges
之前不会持久保存。您可以在多个实体中进行更改并一次性存储它们。这称为Unit of Work pattern。您无法选择性地指定要保存的修改的已附加实体。
将这两个模式组合起来,您将看到一些有趣的效果。您在WPF应用程序中拥有一个实体的唯一实例。即使更改尚未持久保存(提交),对实体所做的任何更改都会影响整个应用程序。在大多数情况下,这不是您想要的。假设您在WPF应用程序中有一个编辑表单。您正在使用实体并决定取消复杂的编辑(更改值,添加相关实体,删除其他相关实体等)。但是实体已在共享上下文中被修改。你会怎么做?提示:我不知道任何关于ObjectContext
的CancelChanges或UndoChanges。
我认为我们不需要讨论服务器场景。仅在多个HTTP请求或Web服务调用之间共享单个实体会使您的应用程序无用。任何请求都可以触发SaveChanges
并保存来自另一个请求的部分数据,因为您将所有这些请求共享为单个工作单元。这还将带来另一个问题-上下文和上下文中的实体或上下文使用的数据库连接的任何操作不是线程安全的。
即使是只读应用程序,全局上下文也不是一个好的选择,因为每次查询应用程序时,您都希望获取最新的数据。