【发布时间】:2020-08-23 21:55:39
【问题描述】:
我正在使用asp.net core 和Entity Framework Core。我的场景是,我想在运行时根据HttpContext查询字符串值更改连接字符串。
我正在尝试将ResolvedParameter 与Reflection components 作为documented 传递。但是,当我解决这个问题时,它没有被注册。下面,我附上了我的代码 sn-p。
Autofac 注册类:
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder)
{
builder.RegisterType(typeof(DbContextOptionsFactory))
.As(typeof(IDbContextOptionsFactory))
.InstancePerRequest();
builder.RegisterType<AppDbContext>()
.As(typeof(IDbContext))
.WithParameter(
new ResolvedParameter(
(pi, cc) => pi.Name == "options",
(pi, cc) => cc.Resolve<IDbContextOptionsFactory>().Get()));
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.SingleInstance();
}
}
public interface IDbContextOptionsFactory
{
DbContextOptions<AppDbContext> Get();
}
public class DbContextOptionsFactory : IDbContextOptionsFactory
{
public DbContextOptions<AppDbContext> Get()
{
try
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<AppDbContext>();
if (EngineContext.Current.Resolve<IHttpContextAccessor>().HttpContext.Request.QueryString.ToString().ToLower().Contains("app1"))
DbContextConfigurer.Configure(builder, configuration.GetConnectionString("app1"));
else if (EngineContext.Current.Resolve<IHttpContextAccessor>().HttpContext.Request.QueryString.ToString().ToLower().Contains("app2"))
DbContextConfigurer.Configure(builder, configuration.GetConnectionString("app2"));
return builder.Options;
}
catch (Exception)
{
throw;
}
}
}
public class DbContextConfigurer
{
public static void Configure(DbContextOptionsBuilder<AppDbContext> builder, string connectionString)
{
builder.UseSqlServer(connectionString);
}
}
AppDbContext:
public class AppDbContext : DbContext, IDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
Assembly assemblyWithConfigurations = typeof(IDbContext).Assembly;
builder.ApplyConfigurationsFromAssembly(assemblyWithConfigurations);
}
//..
//..
}
在运行时,我遇到错误。
处理请求时发生未处理的异常。
DependencyResolutionException:找不到任何构造函数 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' 类型 'AppDbContext' 可以用可用的调用 服务和参数:无法解析参数 'Microsoft.EntityFrameworkCore.DbContextOptions
1[AppDbContext] options' of constructor 'Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions1[AppDbContext])'。 Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo[] 可用的构造函数,IComponentContext 上下文, IEnumerable参数)
我试过answered here..但是,不行。
【问题讨论】:
-
您是否尝试过仅注册选项?
builder.Register(c => c.Resolve<IDbContextOptionsFactory>().Get());? -
@GuruStron 当我将您的代码添加到
builder.RegisterType<AppDbContext>()...上方时,我收到了这个错误。InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext. -
@GuruStron 谢谢! :) 它对代码的修改很少。我已将其发布为答案。根据您的评论和我的理解,
builder.Register()在将委托注册为组件时使用。如果这样做,Autofac在ComponentContext中解析该委托。对吗?
标签: c# asp.net-core dependency-injection autofac dbcontext