控制台程序中实现一个连接一个DBContext实例

最近在控制台程序中使用EFCore,并使用了依赖注入的方式注册调用,但测试时发现不同客户端连接对应了同一个DBContext,导致并发出现问题。踩得坑记录一下。

在ASP.NET Core应用程序中使用EF Core的基本模式通常包括将自定义DbContext类型注册到依赖项注入系统中,然后通过控制器中的构造函数参数获取该类型的实例。这意味着将为每个请求创建一个新的DbContext实例。

public void ConfigureServices(IServiceCollection services)
{
 services.AddDbContext<MCContext >(
     options => options.UseSqlServer(connectionString));
 }




public class TiketsController : ControllerBase
{
    private readonly MCContext _context;

    public TiketsController (MCContext context)
    {
        _context = context;
    }
 }

但是 AddDbContext方法对应的服务生命周期是 Scoped,这样在控制台程序中使用会有一个问题,如果控制台提供一个服务,客户端不同的连接对应的都是一个Context,这样存在并发的问题,如果有个语句出错了,后面操作都将报错。

有AddSingleton、AddScoped、AddTransient 三种方式注册服务,对应的生命周期如下:

  1、Transient:每次从容器 (IServiceProvider)中获取的时候都是一个新的实例

  2、Singleton:每次从同根容器中(同根 IServiceProvider)获取的时候都是同一个实例

  3、Scoped:每次从同一个容器中获取的实例是相同的、

所以在控制台中要用AddTransient的方法注册DbContext:

var Services = new ServiceCollection().AddTransient<DbContext>((c) =>
     {
         var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
         optionsBuilder.UseMySql(connStr, ServerVersion.AutoDetect(connStr))
         .LogTo(Console.WriteLine, LogLevel.Information)
         .EnableSensitiveDataLogging()
         .EnableDetailedErrors();
         //如果有其他依赖的话,可以通过provider.GetService<XX>()来获取
         return new DbContext(optionsBuilder.Options);
     }).BuildServiceProvider();

如果用AddSingleton方法写法:

 var Services = new ServiceCollection().AddSingleton<Func<DbContext>>(() =>
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseMySql(connStr, ServerVersion.AutoDetect(connStr))
        .LogTo(Console.WriteLine, LogLevel.Information)
        .EnableSensitiveDataLogging()
        .EnableDetailedErrors();
        //如果有其他依赖的话,可以通过provider.GetService<XX>()来获取
        return new DbContext(optionsBuilder.Options);
    }).BuildServiceProvider();

参考:

解析 .Net Core 注入——注册服务 | 服务 (lmlphp.com)

(14条消息) EF Core之DBContext生命周期_2Ker的博客-CSDN博客_adddbcontext 生命周期

在ASP.Net Core中每个请求一次创建EF Core上下文 | (1r1g.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要创建一个新的 DbContext 实例,您需要按照以下步骤进行操作: 1. 创建一个继承自 DbContext 的自定义类:首先,在您的项目创建一个新的类,并让它继承自 DbContext。例如,您可以创建一个名为 MyDbContext 的类。 ```csharp public class MyDbContext : DbContext { // 在这里定义您的数据集和数据库表的关联 } ``` 2. 配置数据库连接字符串:在 DbContext,您需要配置数据库连接字符串。可以通过重写 DbContext 类的 OnConfiguring 方法,并通过调用 UseSqlServer、UseMySQL 等方法来指定数据库提供程序连接字符串。这里以 SQL Server 为例: ```csharp public class MyDbContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("YourConnectionString"); } // 在这里定义您的数据集和数据库表的关联 } ``` 3. 定义实体类和数据库表的映射关系:在 DbContext定义实体类和数据库表之间的映射关系。使用 DbSet 属性来定义数据集,使用 Fluent API 或特性注解来配置实体类和数据库表之间的映射关系。 ```csharp public class MyDbContext : DbContext { public DbSet<User> Users { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().ToTable("Users"); // 在这里配置其他实体类和数据库表的映射关系 } } ``` 4. 创建 DbContext 实例:在您的应用程序,可以通过实例化自定义的 DbContext 类来创建 DbContext 实例。 ```csharp using (var dbContext = new MyDbContext()) { // 在这里使用 dbContext 进行数据库操作 } ``` 通过以上步骤,您就可以创建一个新的 DbContext 实例,并在应用程序使用它来进行数据库操作。请注意,根据您的项目需求,可能需要在 DbContext进行进一步的配置和定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值