一、思考
为了应对不同的场景,为了解耦,在需要使用一个上下文实例的地方使用DbContext 注入,在需要创建使用多个上下文实例的地方使用DbContext工厂注入,那么在项目中同时通过依赖注入的方法将DbContext 和 DbContext Factory注入整个项目中是否可行?是否符合规范?
二、实践
1、修改Program.cs文件,使用DI内置IOC容器实现依赖关系注入 DbContext 和 DbContext Factory,代码如下:
Program.cs
// 获取 IConfiguration 实例
var configuration = builder.Configuration;
//依赖关系注入 DbContext
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer(configuration.GetConnectionString("BloggingDatabase"))
);
//依赖关系注入 DbContext 工厂
builder.Services.AddDbContextFactory<ApplicationDbContext>(
options => options.UseSqlServer(configuration.GetConnectionString("BloggingDatabase"))
);
2、运行项目,项目报错出现异常
如果同时使用依赖注入DbContext 和 DbContext工厂,会出现下面的异常:
System.AggregateException:“Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory`1[EF_CORE_TestProject.ApplicationDbContext] Lifetime: Singleton ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory`1[EF_CORE_TestProject.ApplicationDbContext]': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[EF_CORE_TestProject.ApplicationDbContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[EF_CORE_TestProject.ApplicationDbContext]'.)”
上面异常的大概意思是:在使用ASP.NET Core的依赖注入容器时,尝试将一个作用域服务注入到单例服务中。这是因为作用域服务的生命周期比单例服务短,无法在单例服务中使用。是在配置Entity Framework Core的上下文工厂时出现了问题。可能是你尝试将DbContextOptions<ApplicationDbContext>
作为作用域服务注入到了IDbContextFactory<ApplicationDbContext>
的单例服务中。
这是因为在使用AddDbContextFactory
方法时,它会默认将上下文工厂注册为单例服务。而在代码中,同时又将ApplicationDbContext
作为作用域服务注入到了上下文工厂中。要解决这个问题,可以将上下文选项配置为单例服务,以便在上下文工厂中使用。
修改代码如下:
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer(configuration.GetConnectionString("BloggingDatabase")),
ServiceLifetime.Singleton // 将上下文选项配置为单例服务
);
builder.Services.AddDbContextFactory<ApplicationDbContext>(
options => options.UseSqlServer(configuration.GetConnectionString("BloggingDatabase"))
);
运行项目无异常报错。
三、总结
从项目开发规范和代码规范的角度来看,同时将AddDbContext
和AddDbContextFactory
两个方法用于同一个上下文类型是允许的。这样做可以满足不同的需求。
AddDbContext
方法用于将上下文注册为服务,并且可以在需要直接使用上下文的地方进行依赖注入。它还负责管理上下文的生命周期。
AddDbContextFactory
方法用于注册上下文工厂,它可以在需要创建多个上下文实例的地方使用。上下文工厂可以在需要时创建新的上下文实例,而不需要直接依赖于上下文。
同时使用这两个方法的一个潜在问题是,如果你在代码中同时使用了上下文和上下文工厂,可能会导致一些混淆和冲突。因此,在使用时需要明确区分它们的使用场景和目的。另外,需要注意的是,如果你将上下文选项配置为单例服务,那么所有通过上下文工厂创建的上下文实例都将共享相同的上下文选项。这可能会导致一些意外的行为,特别是在多线程环境下。
综上所述,同时使用AddDbContext
和AddDbContextFactory
是允许的,但需要根据具体情况谨慎使用,并清楚它们的区别和适用场景。