我使用的是 asp.net core
与...一起 Entity Framework Core
. 我的方案是,我想在运行时根据以下内容改变连接字符串。HttpContext
查询字符串值。
我试图通过 ResolvedParameter
与 Reflection components
作为 有据可查. 但是,当我解决这个问题时,它没有得到注册。下面,我附上了我的代码片段。
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: 在'AppDbContext'类型上,没有找到任何一个使用'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'的构造函数可以被可用的服务和参数调用。无法解析参数 "Microsoft.EntityFrameworkCore.DbContextOptions"。
1[AppDbContext] options' of constructor 'Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions
1[AppDbContext])'。) Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo[] availableConstructors, IComponentContext context, IEnumerable parameters)
我曾试过 在此回答...但是,没有工作。
我已经解决了这个问题,通过做改变Guru Stron的评论和后续的变化。下面是我的改动。
步骤1.将Autofac注册类改为HttpContext查询字符串值。 更改Autofac注册类如下。
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder)
{
//Removed this code
//builder.RegisterType(typeof(DbContextOptionsFactory))
// .As(typeof(IDbContextOptionsFactory))
// .InstancePerRequest();
//Added this code
builder.Register(c => c.Resolve<IDbContextOptionsFactory>().Get())
.InstancePerDependency(); // <-- Changed this line
builder.RegisterType<AppDbContext>()
.As(typeof(IDbContext))
.WithParameter(
new ResolvedParameter(
(pi, cc) => pi.Name == "options",
(pi, cc) => cc.Resolve<IDbContextOptionsFactory>().Get()))
.InstancePerDependency(); // <-- Added this line
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerDependency(); // <-- Changed this line
}
}
现在,如果你得到的错误:
InvalidOperationException: No database provider has been configured for this DbContext. 可以通过覆盖DbContext.OnConfiguring方法或使用应用程序服务提供者上的AddDbContext来配置提供者。如果使用AddDbContext,那么还要确保你的DbContext类型在其构造函数中接受一个DbContextOptions对象,并将其传递给DbContext的基础构造函数。
通过在下面的代码中添加 AppDbContext
类来解决上述错误。
第2步: 修改了 AppDbContext
(新增 OnConfiguring()
方法)
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);
}
//Added this method
protected override void OnConfiguring(DbContextOptionsBuilder dbContextOptionsBuilder)
{
base.OnConfiguring(dbContextOptionsBuilder);
}
//..
//..
}