使用 DbContextWorking with DbContext

若要使用实体框架来使用 .NET 对象查询、插入、更新和删除数据,您首先需要创建一个模型,该模型将模型中定义的实体和关系映射到数据库中的表。

有了模型后,应用程序与之交互的主类就 System.Data.Entity.DbContext (通常称为上下文类)。 您可以使用与模型关联的 DbContext 来执行以下操作:

  • 编写和执行查询
  • 将查询结果具体化为实体对象
  • 跟踪对这些对象进行的更改
  • 将对象更改保存回数据库
  • 将内存中的对象绑定到 UI 控件

本页提供有关如何管理上下文类的一些指导。

定义 DbContext 派生类Defining a DbContext derived class

使用上下文的建议方法是定义从 DbContext 派生的类,并公开 DbSet 属性,这些属性表示上下文中指定实体的集合。 如果使用的是 EF 设计器,则会为您生成上下文。 如果使用 Code First,则通常会自行编写上下文。

  1. public class ProductContext : DbContext
  2. {
  3. public DbSet<Category> Categories { get; set; }
  4. public DbSet<Product> Products { get; set; }
  5. }

拥有上下文后,可以通过这些属性查询、添加(使用 AddAttach 方法)或在上下文中删除(使用 Remove)实体。 访问上下文对象上的 DbSet 属性表示一个启动查询,该查询返回指定类型的所有实体。 请注意,仅访问属性不会执行查询。 执行以下操作时执行查询:

  • foreach (C#) 或 For Each (Visual Basic) 语句枚举对象。
  • 它通过集合操作(如 ToArrayToDictionaryToList)进行枚举。
  • 在查询的最外面部分指定 LINQ 运算符,例如 FirstAny
  • 如果在上下文中未找到具有指定键的实体,则调用以下方法之一: Load 扩展方法 DbEntityEntry.ReloadDatabase.ExecuteSqlCommandDbSet<T>.Find

生存期Lifetime

上下文的生存期在实例创建时开始,并在实例被释放或被回收时结束。 如果希望在块的末尾释放上下文控制的所有资源,请使用。 使用时,编译器会自动创建 try/finally 块并在finally块中调用 dispose。

  1. public void UseProducts()
  2. {
  3. using (var context = new ProductContext())
  4. {
  5. // Perform data access using the context
  6. }
  7. }

下面是决定上下文生存期时的一些一般指导原则:

  • 使用 Web 应用程序时,请为每个请求使用上下文实例。
  • 使用 Windows Presentation Foundation (WPF)或 Windows 窗体时,请使用每个窗体的上下文实例。 这使你可以使用上下文提供的更改跟踪功能。
  • 如果上下文实例是由依赖关系注入容器创建的,则该容器通常负责释放上下文。
  • 如果上下文是在应用程序代码中创建的,请记得在不再需要时释放上下文。
  • 使用长时间运行的上下文时,请考虑以下事项:
    • 在将更多对象及其引用加载到内存中时,上下文的内存消耗可能会迅速增加。 这可能会导致性能问题。
    • 上下文不是线程安全的,因此不应在多个线程上同时对其执行工作。
    • 如果异常导致上下文处于不可恢复的状态,则整个应用程序可能会终止。
    • 随着查询数据的时间和更新数据的时间的差距增大,出现与并发性相关的问题的可能性将会增加。

连接Connections

默认情况下,上下文管理与数据库的连接。 上下文会根据需要打开和关闭连接。 例如,上下文打开一个连接来执行查询,然后在处理完所有结果集后关闭连接。

在某些情况下,您需要加强控制应在哪些情况下打开和关闭连接。 例如,使用 SQL Server Compact 时,通常建议在应用程序的生存期内维护单独的数据库打开连接,以提高性能。 您可以使用 Connection 属性手动管理此过程。