我正在尝试根据每个http请求标头设置我的DbContext的连接字符串。是否有可能在.NET Core中这样做?我在MVC5中做到了,但我无法在.NET核心中实现它。
目前
public void ConfigureServices(IServiceCollection services)
{
// ...
}
我不知道http标头,所以我在哪里可以做到?
答案 0 :(得分:8)
你应该可以做这样的事情来使用DbContext
类型实例化中的HTTP请求内容:
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<HttpContext>(p => p.GetService<IHttpContextAccessor>()?.HttpContext);
services.AddDbContext<MyDbContext>();
var descriptor = new ServiceDescriptor(
typeof(DbContextOptions<MyDbContext>),
DbContextOptionsFactory,
ServiceLifetime.Scoped);
var descriptorNonGeneric = new ServiceDescriptor(
typeof(DbContextOptions),
typeof(DbContextOptions<MyDbContext>),
ServiceLifetime.Scoped);
services.Replace(descriptor);
services.Replace(descriptorNonGeneric);
// ...
}
private DbContextOptions<MyDbContext> DbContextOptionsFactory(IServiceProvider provider)
{
var httpContext = provider.GetService<HttpContext>();
// here we have the complete HttpContext
var myHeader = httpContext.Request.Headers["MyHeader"];
var connectionString = GetConnectionStringFromHeader(myHeader);
var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
optionsBuilder.UseSqlServer(connectionString);
return optionsBuilder.Options;
}
因为EFCore的AddDbContext<TDbContext>
扩展方法已经将DbContextOptions
注册为单例,我们需要覆盖此注册并添加我们自己的DbContextOption
工厂方法,该方法使用{{1}并且以HttpContext
生命周期执行。
这样我们可以在每个请求上更改选项(包括连接字符串)。
答案 1 :(得分:0)
这样,您可以更加简化
services.AddScoped<ISqlConnectionContext, SqlConnectionContext>();
services.AddDbContext<SqlDbContext>((sp, builder) =>
builder.UseSqlServer(sp.GetRequiredService<ISqlConnectionContext>().GetConnectionString()));
SqlConnectionContext
现在可以按照您想要的任何方式实现。
例如,使用IHttpContextAccessor
。