简体   繁体   English

实体框架和连接池

[英]Entity Framework and Connection Pooling

I've recently started to use the Entity Framework 4.0 in my .NET 4.0 application and am curious about a few things relating to pooling. 我最近开始在.NET 4.0应用程序中使用Entity Framework 4.0,并对与池相关的一些事情感到好奇。

  1. Connection pooling as I know is managed by the ADO.NET data provider, in my case that of MS SQL server. 据我所知,连接池是由ADO.NET数据提供程序管理的,在我的情况下是由MS SQL服务器管理的。 Does this apply when you instantiate a new entities context ( ObjectContext ), ie the parameterless new MyDatabaseModelEntities() ? 实例化新实体上下文( ObjectContext ),即无参数的new MyDatabaseModelEntities()时,这是否适用?

  2. What are the advantages and disadvantages of a) creating a global entities context for the application (ie one static instance) or b) creating and exposing an entities context for each given operation/method, with a using block. a)为应用程序创建全局实体上下文(即一个静态实例)或b) using块为每个给定的操作/方法创建和公开实体上下文的优缺点是什么?

  3. Any other recommendations, best practices, or common approaches for certain scenarios that I should know about? 对于某些情况,我应该知道其他任何建议,最佳做法或通用方法吗?

  1. Connection pooling is handled as in any other ADO.NET application. 连接池的处理方式与任何其他ADO.NET应用程序一样。 Entity connection still uses traditional database connection with traditional connection string. 实体连接仍然使用传统的数据库连接和传统的连接字符串。 I believe you can turn off connnection pooling in connection string if you don't want to use it. 我相信,如果您不想使用连接字符串,则可以关闭连接池。 (read more about SQL Server Connection Pooling (ADO.NET) ) (了解有关SQL Server连接池(ADO.NET)的更多信息)
  2. Never ever use global context. 永远不要使用全局上下文。 ObjectContext internally implements several patterns including Identity Map and Unit of Work. ObjectContext在内部实现了几种模式,包括身份映射和工作单元。 Impact of using global context is different per application type. 每种应用程序类型使用全局上下文的影响是不同的。
  3. For web applications use single context per request. 对于Web应用程序,每个请求使用单个上下文。 For web services use single context per call. 对于Web服务,每个调用使用单个上下文。 In WinForms or WPF application use single context per form or per presenter. 在WinForms或WPF应用程序中,每个表单或每个演示者都使用单个上下文。 There can be some special requirements which will not allow to use this approach but in most situation this is enough. 可能会有一些特殊的要求,这些要求不允许使用这种方法,但是在大多数情况下,这就足够了。

If you want to know what impact has single object context for WPF / WinForm application check this article . 如果您想知道对WPF / WinForm应用程序单个对象上下文有什么影响,请查阅本文 It is about NHibernate Session but the idea is same. 它是关于NHibernate Session的,但是想法是相同的。

Edit: 编辑:

When you use EF it by default loads each entity only once per context. 使用EF时,默认情况下,每个上下文仅加载每个实体一次。 The first query creates entity instace and stores it internally. 第一个查询创建实体实例并将其存储在内部。 Any subsequent query which requires entity with the same key returns this stored instance. 任何随后的需要实体具有相同键的查询都将返回此存储的实例。 If values in the data store changed you still receive the entity with values from the initial query. 如果数据存储中的值发生更改,您仍然会收到来自初始查询的带有值的实体。 This is called Identity map pattern . 这称为身份映射模式 You can force the object context to reload the entity but it will reload a single shared instance. 您可以强制对象上下文重新加载实体,但是它将重新加载单个共享实例。

Any changes made to the entity are not persisted until you call SaveChanges on the context. 除非您在上下文上调用SaveChanges ,否则对实体所做的任何更改都不会SaveChanges You can do changes in multiple entities and store them at once. 您可以在多个实体中进行更改并立即存储它们。 This is called Unit of Work pattern . 这称为工作单元模式 You can't selectively say which modified attached entity you want to save. 您无法选择性地说出要保存的修改后的附加实体。

Combine these two patterns and you will see some interesting effects. 结合这两种模式,您将看到一些有趣的效果。 You have only one instance of entity for the whole application. 整个应用程序只有一个实体实例。 Any changes to the entity affect the whole application even if changes are not yet persisted (commited). 对实体的任何更改都会影响整个应用程序,即使更改尚未持久(提交)。 In the most times this is not what you want. 在大多数情况下,这不是您想要的。 Suppose that you have an edit form in WPF application. 假设您在WPF应用程序中有一个编辑表单。 You are working with the entity and you decice to cancel complex editation (changing values, adding related entities, removing other related entities, etc.). 您正在使用该实体,并且决定取消复杂的编辑(更改值,添加相关实体,删除其他相关实体等)。 But the entity is already modified in shared context. 但是该实体已经在共享上下文中被修改。 What will you do? 你会怎么做? Hint: I don't know about any CancelChanges or UndoChanges on ObjectContext . 提示:我不知道ObjectContext上有任何CancelChanges或UndoChanges。

I think we don't have to discuss server scenario. 我认为我们不必讨论服务器方案。 Simply sharing single entity among multiple HTTP requests or Web service calls makes your application useless. 在多个HTTP请求或Web服务调用之间简单地共享单个实体会使您的应用程序无用。 Any request can just trigger SaveChanges and save partial data from another request because you are sharing single unit of work among all of them. 任何请求都只能触发SaveChanges并保存来自另一个请求的部分数据,因为您要在所有请求之间共享单个工作单元。 This will also have another problem - context and any manipulation with entities in the context or a database connection used by the context is not thread safe. 这也将带来另一个问题-上下文,对上下文中的实体或上下文使用的数据库连接进行的任何操作都不是线程安全的。

Even for a readonly application a global context is not a good choice because you probably want fresh data each time you query the application. 即使对于只读应用程序,全局上下文也不是一个好选择,因为每次查询应用程序时您可能都希望有新数据。

According to Daniel Simmons: 据丹尼尔·西蒙斯说:

Create a new ObjectContext instance in a Using statement for each service method so that it is disposed of before the method returns. 在Using语句中为每个服务方法创建一个新的ObjectContext实例,以便在方法返回之前将其丢弃。 This step is critical for scalability of your service. 此步骤对于服务的可伸缩性至关重要。 It makes sure that database connections are not kept open across service calls and that temporary state used by a particular operation is garbage collected when that operation is over. 它可以确保数据库连接不会在服务调用之间保持打开状态,并且确保特定操作使用的临时状态在该操作结束时不会被垃圾回收。 The Entity Framework automatically caches metadata and other information it needs in the app domain, and ADO.NET pools database connections, so re-creating the context each time is a quick operation. 实体框架自动在应用程序域中缓存元数据和它所需的其他信息,而ADO.NET则池化数据库连接,因此每次重新创建上下文都是一项快速的操作。

This is from his comprehensive article here: 这来自他的综合文章:

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

I believe this advice extends to HTTP requests, so would be valid for ASP.NET. 我认为此建议适用于HTTP请求,因此对于ASP.NET是有效的。 A stateful, fat-client application such as a WPF application might be the only case for a "shared" context. 有状态的胖客户端应用程序(例如WPF应用程序)可能是“共享”上下文的唯一情况。

Accoriding to EF6 (4,5 also) documentation: https://msdn.microsoft.com/en-us/data/hh949853#9 根据EF6(也包括4,5)文档: https ://msdn.microsoft.com/zh-cn/data/hh949853#9

9.3 Context per request 9.3每个请求的上下文

Entity Framework's contexts are meant to be used as short-lived instances in order to provide the most optimal performance experience . 实体框架的上下文旨在用作短期实例,以提供最佳的性能体验 Contexts are expected to be short lived and discarded, and as such have been implemented to be very lightweight and reutilize metadata whenever possible. 预期上下文将短暂存在并被丢弃,因此上下文已实现为非常轻量级,并在可能的情况下重新使用元数据。 In web scenarios it's important to keep this in mind and not have a context for more than the duration of a single request. 在Web场景中,请记住这一点,并且不要让上下文超出单个请求的持续时间,这一点很重要。 Similarly, in non-web scenarios, context should be discarded based on your understanding of the different levels of caching in the Entity Framework. 同样,在非Web场景中,应根据您对实体框架中不同级别的缓存的了解来丢弃上下文。 Generally speaking, one should avoid having a context instance throughout the life of the application, as well as contexts per thread and static contexts. 一般而言,应该避免在应用程序的整个生命周期中都具有上下文实例,以及每个线程的上下文和静态上下文。

Below code helped my object to be refreshed with fresh database values. 下面的代码用新的数据库值帮助刷新了我的对象。 The Entry(object).Reload() command forces the object to recall database values Entry(object).Reload()命令强制对象重新调用数据库值

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM