首页 文章

实体框架和连接池

提问于
浏览
256

我最近开始在.NET 4.0应用程序中使用Entity Framework 4.0,并对与池化相关的一些事情感到好奇 .

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

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

  • 我应该了解的某些场景的任何其他建议,最佳实践或常用方法?

4 回答

  • 359
    • 连接池的处理方式与任何其他ADO.NET应用程序一样 . 实体连接仍然使用传统的数据库连接与传统的连接字符串 . 我相信如果您不想使用它,可以关闭连接字符串中的连接池 . (了解更多关于SQL Server Connection Pooling (ADO.NET)

    • 永远不要使用全局上下文 . ObjectContext在内部实现了几种模式,包括Identity Map和Unit of Work . 使用全局上下文的影响因应用程序类型而异 .

    • 对于Web应用程序,每个请求使用单个上下文 . 对于Web服务,每次调用使用单个上下文 . 在WinForms或WPF应用程序中,每个表单或每个演示者使用单个上下文 . 可能有一些特殊要求不允许使用这种方法,但在大多数情况下这已经足够了 .

    如果您想知道WPF / WinForm应用程序的单个对象上下文有什么影响,请检查article . 这是关于NHibernate Session,但想法是一样的 .

    Edit:

    当您使用EF时,它默认情况下每个上下文仅加载一个实体一次 . 第一个查询创建实体实例并在内部存储它 . 任何需要具有相同键的实体的后续查询都会返回此存储的实例 . 如果数据存储中的值发生更改,您仍会收到包含初始查询值的实体 . 这叫做 Identity map pattern . 您可以强制对象上下文重新加载实体,但它将重新加载单个共享实例 .

    在上下文中调用 SaveChanges 之前,对实体所做的任何更改都不会保留 . 您可以在多个实体中进行更改并立即存储它们 . 这称为 Unit of Work pattern . 您无法有选择地说出要保存的已修改附加实体 .

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

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

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

  • 64

    下面的代码帮助我的对象刷新了新的数据库值 . Entry(object).Reload()命令强制对象调用数据库值

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

    丹尼尔西蒙斯说:

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

    这是他在这里的综合文章:

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

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

  • 2

    符合EF6(4,5也)文件:https://msdn.microsoft.com/en-us/data/hh949853#9

    9.3 Context per request

    Entity Framework’s contexts are meant to be used as short-lived instances in order to provide the most optimal performance experience . 预期上下文将是短暂的并且被丢弃,因此已经被实现为非常轻量级并且每当重新使用元数据时可能 . 在Web场景中,重要的是要牢记这一点,并且没有超过单个请求持续时间的上下文 . 同样,在非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.

相关问题