在许多 Web 应用程序中,每个 HTTP 请求都对应于单个工作单元。这使得上下文生存期与请求的生存期相关,成为 Web 应用程序的一个良好默认值。
使用依赖关系注入配置 ASP.NET Core 应用程序。可以在 Startup.cs 文件的 ConfigureServices 方法中,用 AddDbContext 扩展方法将 EF Core 添加到此处进行配置。
本文中我使用的是 MySQL 数据库,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
#region 配置MySQL数据库
var connectionString = "server=数据库部署的服务器地址;user=数据库登录用户名;password=数据库登录密码;database=数据库名;charset=utf8";
var serverVersion = new MySqlServerVersion(new Version(5, 7, 22));
services.AddDbContext<CustomAppDbContext>(
dbContextOptions => dbContextOptions
.UseMySql(connectionString, serverVersion)
);
#endregion
}
复制代码
此示例将名为 CustomAppDbContext 的 DbContext 子类注册为 ASP.NET Core 应用程序服务提供程序(也称为依赖关系注入容器)中的作用域服务。上下文配置为使用 MySQL 数据库提供程序,并将从 ASP.NET Core 配置读取连接字符串。在 ConfigureServices 中的何处调用 AddDbContext 通常不重要。 F12转到 DbContext 类的定义,发现其有参构造函数定义形式为: public DbContext([NotNullAttribute] DbContextOptions options);
CustomAppDbContext 类必须公开具有 DbContextOptions 参数的公共构造函数。这是将 AddDbContext 的上下文配置传递到 DbContext 的方式。例如:
public class CustomAppDbContext : DbContext
{
public CustomAppDbContext(DbContextOptions<CustomAppDbContext> options) : base(options)//调用父类的构造函数
{
}
public DbSet<Student> Student { get; set; }
}
复制代码
其中 Student 类如下所示:
public partial class Student
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime? JoinTime { get; set; }
public int Sex { get; set; }
}
复制代码
然后,CustomAppDbContext 可以通过构造函数注入在 ASP.NET Core 控制器或其他服务中使用。例如:
public class MyController : Controller
{
private readonly CustomAppDbContext _context;
public MyController(CustomAppDbContext context)//构造函数
Entity Framework Core 不支持在同一 DbContext 实例上运行多个并行操作。这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。因此,始终立即 await 异步调用,或对并行执行的操作使用单独的 DbContext 实例。
当 EF Core 检测到尝试同时使用 DbContext 实例的情况时,你将看到 InvalidOperationException,其中包含类似于以下内容的消息: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe.
翻译成中文就是: 在上一个操作完成之前,在此上下文上启动了第二个操作。这通常是由不同线程使用相同的DbContext实例引起的,但不保证实例成员是线程安全的。
当并发访问未被检测到时,可能会导致未定义的行为、应用程序崩溃和数据损坏。
七、异步操作缺陷