有没有办法工厂注入自定义 DbContext?
Is there a way to factory inject a custom DbContext?
...也许在 EF Core 扩展的 AddDbContextFactory<TContext, TFactory>
中使用 TFactory?
我只见过 AddDbContextFactory being used with just the TContext generic. They're always very explicit to say you have to use a using statement。
在类似情况下(当我在 Angular 中使用 Class 或在 .NET Core 中使用 AddScoped 时),我将变量 I want to see in a constructor 作为第一个泛型参数和第二个通用参数实际注入的内容。你知道,比如:
services.AddScoped<IService, RealService>();
显然,
并非如此
services.AddDbContextFactory<ADbContextIHaveBeenInjecting, AFactoryThatWillReturnADbContextIHaveBeenInjecting>();
我希望这会消除整个 using 的需要。
有没有另一种方法可以做到这一点,而不必重新编写每个注入的 DbContext 以符合他们的规定:
public void DoSomething()
{
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
}
正如我所说,我希望为工厂使用这样的东西:
public class MyDbContextFactory : IDbContextFactory<MyDbContext>
{
public MyDbContextFactory(DbContextOptions options)
{
}
public MyDbContext CreateDbContext()
{
var ProviderName = GetProviderName();
switch (ProviderName)
{
case "System.Data.SqlClient":
return new SqlServerDbContext(new DbContextOptionsBuilder<SqlServerDbContext>().UseSqlServer(ConnectionString).Options);
case "Npgsql":
return new PostgreSqlDbContext(new DbContextOptionsBuilder<PostgreSqlDbContext>().UseNpgsql(ConnectionString).Options);
default:
throw new NullReferenceException("Missing provider name for DbContext. Should be Npgsql or System.Data.SqlClient");
}
}
}
然后,在 Startup.cs ConfigureServices 中进行设置,例如:
services.AddDbContextFactory<MyDbContext, MyDbContextFactory>();
所以我可以像这样注入 class:
public class MyController : BaseApiController
{
private readonly MyDbContext _myDbContext;
public MyController(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
[HttpGet("GetACount")]
public IActionResult GetACount()
{
var count = _myDbContext.MyRecord.Count();
return Ok(count);
}
...
有没有办法使用 AddDbContextFactory 来做到这一点? TFactory 究竟是做什么用的?还有其他方法吗?
依赖注入具体 class。按类型创建工厂 select subclass。使用私有 DbContext _dbContext 创建父级 class。从父class继承子class,并用子class的:base(dbContext)调用父class构造函数。父 class 现在可以在其方法中访问子 class 上下文。子class可以通过设置子class的数据上下文来共享父class的方法(添加,select,更新和删除)。 subclass 将在其构造函数中依赖注入特定的 dbcontext 并在其构造函数中设置父 class dbcontext 变量。然后 subclass 存储库 class 可以访问其主体中的基本 class 方法。
在启动时定义子class 存储库模式
在 public void ConfigureServices(IServiceCollection 服务)
var connectionString = Configuration.GetConnectionString("ABCContext_DbCoreConnectionString");
services.AddDbContext<ABCContext>(options1 => options1.UseSqlServer(connectionString));
services.AddTransient<IRepositoryMySubclass, RepositoryMySubclass>();
sub class
public RepositorySubclass(ABCContext dbContext) : base(dbContext)
{
_dbContext = dbContext;
}
DbContextFactory 特别 旨在要求您管理 DbContext 的生命周期,因为 Blazor 服务器应用程序不使用像 [=21= 这样的 Scope-per-Http 请求] Core 可以,因此 Scoped DbContext 将不起作用。
如果您想要 Scoped DbContext,只需使用 .AddDbContext
而不是 .AddDbContextFactory
。
如果您已经注册了 DbContextFactory,但仍想直接在您的服务中注入作用域 DbContext,请按如下方式注册:
services.AddScoped<MyDbContext>(sp =>
{
var cf = sp.GetRequiredService<IDbContextFactory<MyDbContext>>();
var db = cf.CreateDbContext();
return db;
});
...也许在 EF Core 扩展的 AddDbContextFactory<TContext, TFactory>
中使用 TFactory?
我只见过 AddDbContextFactory
在类似情况下(当我在 Angular 中使用 Class 或在 .NET Core 中使用 AddScoped 时),我将变量 I want to see in a constructor 作为第一个泛型参数和第二个通用参数实际注入的内容。你知道,比如:
services.AddScoped<IService, RealService>();
显然,
并非如此services.AddDbContextFactory<ADbContextIHaveBeenInjecting, AFactoryThatWillReturnADbContextIHaveBeenInjecting>();
我希望这会消除整个 using 的需要。
有没有另一种方法可以做到这一点,而不必重新编写每个注入的 DbContext 以符合他们的规定:
public void DoSomething()
{
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
}
正如我所说,我希望为工厂使用这样的东西:
public class MyDbContextFactory : IDbContextFactory<MyDbContext>
{
public MyDbContextFactory(DbContextOptions options)
{
}
public MyDbContext CreateDbContext()
{
var ProviderName = GetProviderName();
switch (ProviderName)
{
case "System.Data.SqlClient":
return new SqlServerDbContext(new DbContextOptionsBuilder<SqlServerDbContext>().UseSqlServer(ConnectionString).Options);
case "Npgsql":
return new PostgreSqlDbContext(new DbContextOptionsBuilder<PostgreSqlDbContext>().UseNpgsql(ConnectionString).Options);
default:
throw new NullReferenceException("Missing provider name for DbContext. Should be Npgsql or System.Data.SqlClient");
}
}
}
然后,在 Startup.cs ConfigureServices 中进行设置,例如:
services.AddDbContextFactory<MyDbContext, MyDbContextFactory>();
所以我可以像这样注入 class:
public class MyController : BaseApiController
{
private readonly MyDbContext _myDbContext;
public MyController(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
[HttpGet("GetACount")]
public IActionResult GetACount()
{
var count = _myDbContext.MyRecord.Count();
return Ok(count);
}
...
有没有办法使用 AddDbContextFactory 来做到这一点? TFactory 究竟是做什么用的?还有其他方法吗?
依赖注入具体 class。按类型创建工厂 select subclass。使用私有 DbContext _dbContext 创建父级 class。从父class继承子class,并用子class的:base(dbContext)调用父class构造函数。父 class 现在可以在其方法中访问子 class 上下文。子class可以通过设置子class的数据上下文来共享父class的方法(添加,select,更新和删除)。 subclass 将在其构造函数中依赖注入特定的 dbcontext 并在其构造函数中设置父 class dbcontext 变量。然后 subclass 存储库 class 可以访问其主体中的基本 class 方法。
在启动时定义子class 存储库模式
在 public void ConfigureServices(IServiceCollection 服务)
var connectionString = Configuration.GetConnectionString("ABCContext_DbCoreConnectionString");
services.AddDbContext<ABCContext>(options1 => options1.UseSqlServer(connectionString));
services.AddTransient<IRepositoryMySubclass, RepositoryMySubclass>();
sub class
public RepositorySubclass(ABCContext dbContext) : base(dbContext)
{
_dbContext = dbContext;
}
DbContextFactory 特别 旨在要求您管理 DbContext 的生命周期,因为 Blazor 服务器应用程序不使用像 [=21= 这样的 Scope-per-Http 请求] Core 可以,因此 Scoped DbContext 将不起作用。
如果您想要 Scoped DbContext,只需使用 .AddDbContext
而不是 .AddDbContextFactory
。
如果您已经注册了 DbContextFactory,但仍想直接在您的服务中注入作用域 DbContext,请按如下方式注册:
services.AddScoped<MyDbContext>(sp =>
{
var cf = sp.GetRequiredService<IDbContextFactory<MyDbContext>>();
var db = cf.CreateDbContext();
return db;
});