Skip to main content

对象上下文生存周期、配置和初始化

本文深入探讨了对象上下文的生存周期、配置与初始化,以及如何正确使用对象上下文的基本知识。

提示

对象上下文通常是指继承自ObjectContext的实例对象,后续教程中出现的ObjectContext均代表对象上下文。

对象上下文

所有上下文操作对象都应集成继承自ObjectContext;,ObjectContext具有泛型参数和非泛型参数两种形式。如果继承泛型ObjectContext,则上下文配置提供者必须具有一个无参构造函数。

/// <summary>
/// 学生与班级对象上下文
/// </summary>
public class StudentAndClassContext : ObjectContext<MySqlContextConfiger>
{
/// <summary>
/// 学生对象集合
/// </summary>
public ObjectSet<Student> Students { get; set; }

/// <summary>
/// 班级对象集合
/// </summary>
public ObjectSet<Class> Classes { get; set; }
}

此外,我们还有定义无泛型参数的方法,该方法不强制要求具有无参构造函数,而是在创建上下文时传入ContextConfigProvider。之前定义的上下文提供者都继承自SQLContextConfigProvider,而ContextConfigProvider则是SQLContextConfigProvider的基类。

/// <summary>
/// 无泛型参数
/// </summary>
public class StudentAndCalssContextWithNoGeneric : ObjectContext
{
/// <summary>
/// 构造ObjectContext对象
/// </summary>
/// <param name="provider"></param>
public StudentAndCalssContextWithNoGeneric(ContextConfigProvider provider) : base(provider)
{
}

/// <summary>
/// 学生对象集合
/// </summary>
public ObjectSet<Student> Students { get; set; }

/// <summary>
/// 班级对象集合
/// </summary>
public ObjectSet<Class> Classes { get; set; }
}

当上下文配置提供者必须使用带参数的构造函数时,可以采用这种方式来定义上下文。

生存周期

ObjectContext的生命周期从其创建的那一刻开始,由系统自动回收,无需手动释放。每个ObjectContext实例主要用于单个工作单元,因此其存在的时间通常较短。

使用 Obase 时的典型工作单元包括:

  • 创建 ObjectContext 实例
  • 根据上下文跟踪实体实例。 实体将在以下情况下被跟踪
    • 正在从查询返回
    • 正在添加或附加到上下文
  • 根据需要对所跟踪的实体进行更改以实现业务规则
  • 调用 SaveChanges。 Obase 检测所做的更改,并将这些更改写入数据库。

初始化DbContext

var context = new DbContext();
//附加在上下文内
context.Students.Attach(model);
//保存
context.SaveChanges();

依赖注入

在许多 Web 应用程序中,每个 HTTP 请求都对应于单个工作单元。 这使得上下文生存期与请求的生存期相关,成为 Web 应用程序的一个良好默认值。

使用依赖关系注入配置 ASP.NET Core 应用程序。 可以使用 Startup.cs 的 ConfigureServices 方法中的 AddTransient 将 Obase 添加到此配置。 例如:

public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ContextConfiguration>():
services.AddTransient<SampleObjectContext>();
}

SampleObjectContext 可以通过构造函数注入在 ASP.NET Core 控制器或其他服务中使用。 例如:

public class MyController
{
private readonly SampleObjectContext _context;

public MyController(SampleObjectContext context)
{
_context = context;
}
}

最终结果是为每个请求创建一个 SampleObjectContext 实例,并传递给控制器,以在请求结束后释放前执行工作单元。

避免跨线程使用

Obase不支持在同一 ObjectContext 实例上运行多个并行操作。 这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。 因此,始终立即 await 异步调用,或对并行执行的操作使用单独的 ObjectContext 实例。 如果在多线程中使用,可能会导致未定义的行为、应用程序崩溃和数据损坏。