您好我已经将我的UnitOfWork创建为通用的,并且在运行时它应该在TContext传递的基础上使用DBContextOption Builder创建新的DB上下文实例我已经在autofac中注册了Mention DB Context但是如何在DB Context Constructor Level < / p>
数据库上下文1实现
public class DBContext1 : DbContext
{
public DBContext1(DbContextOptions<DBContext1> options1) : base(options1)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
数据库上下文2实现
public class DBContext2 : DbContext
{
public DBContext2(DbContextOptions<DBContext2> options2) : base(options2)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
IUnitOfWork接口实现
public interface IUnitOfWork<TContext> where TContext : DbContext, IDisposable
{
}
UnitOfWork类实现
public class UnitOfWork<TContext> : IDisposable, IUnitOfWork<TContext> where TContext : DbContext, new()
{
private DbContext _context;
public UnitOfWork()
{
_context = new TContext();
}
}
StartUp Class Implemetation
public class Startup
{
protected IConfiguration _configuration { get; set; }
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddEntityFrameworkSqlServer()
.AddDbContext<DBContext1>(options =>
options.UseSqlServer(_configuration.GetConnectionString("DBContext1")))
.AddDbContext<DBContext2>(options =>
options.UseSqlServer(_configuration.GetConnectionString("DBContext2")));
/* Autofac DI Configuration with registering DBContext/DataModule/ServiceModule to it */
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(_configuration).AsImplementedInterfaces().ExternallyOwned();
var autoFacOptions1 = new DbContextOptionsBuilder<DBContext1>().UseSqlServer(_configuration.GetConnectionString("DBContext1")).Options;
var autoFacOptions2 = new DbContextOptionsBuilder<DBContext2>().UseSqlServer(_configuration.GetConnectionString("DBContext2")).Options;
containerBuilder.Register(c => new DBContext1(autoFacOptions1)).As<DbContext>();
containerBuilder.Register(c => new DBContext2(autoFacOptions2)).As<DbContext>();
containerBuilder.RegisterModule<DataModule>();
containerBuilder.RegisterModule<ServiceModule>();
containerBuilder.Register<String>(c => Guid.NewGuid().ToString())
.Named<String>("correlationId")
.InstancePerLifetimeScope();
containerBuilder.Populate(services);
var container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Account}/{action=Login}/{id?}");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
我可以根据需要实现多个DBContext调用,但我必须创建默认构造函数&amp; DB上下文中的连接字符串,如下所述
数据库上下文1实现
public class DBContext1 : DbContext
{
public DBContext1()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Data Source=Server;Database=DB;User Id=UserID;Password=Password;Integrated Security=False;MultipleActiveResultSets=true;");
}
public DBContext1(DbContextOptions<DBContext1> options1) : base(options1)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
数据库上下文2实现
public class DBContext2 : DbContext
{
public DBContext2()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Data Source=Server;Database=DB;User Id=UserID;Password=Password;Integrated Security=False;MultipleActiveResultSets=true;");
}
public DBContext2(DbContextOptions<DBContext2> options2) : base(options2)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
请帮我调用DBContext1&amp;的参数化构造函数。 DBContext2使用autofac依赖解析器
答案 0 :(得分:1)
好吧,如果您正在使用autofac来解决依赖关系,那么为什么要尝试为它做好工作呢? :)这是您的代码的主要问题。
首先,您不需要明确注册IConfiguration。它已在IServiceCollection
中注册,已传递给ConfigureServices()
方法,并会在containerBuilder.Populate(services)
来电期间由autofac自动提取。你可以删除这个注册,什么都不会改变。
此外,您在服务集合和autofac容器构建器中重新注册了DbContext
两次。这不是必要的,因为后者将有效地取代前者。此外,它会对注册的内容产生混淆,这将在何处以及如何实现这一目标。选择一种注册方法并坚持使用它会更好。
下一个问题:你如何对你的工作单元进行单元测试?它对DbContext有很强的依赖性,它的生命周期是你在测试中无法控制的。这正是您需要autofac的原因:管理组件的依赖关系,让您专注于组件的目的而不是辅助内容。
下一个混乱点在这里:
containerBuilder.Register(c => new DBContext1(autoFacOptions1)).As<DbContext>();
containerBuilder.Register(c => new DBContext2(autoFacOptions2)).As<DbContext>();
通过这样做,您实际上正在用第二个替换第一个db上下文注册。 从这一点开始,无法在应用程序的任何位置注入 EDITED:您仍然可以注入DbContext派生实现的集合并在其中查找DBContext1。 ..但那看起来很奇怪。DBContext1
。
总而言之,这可以通过更加干净和直接的方式完成。
<强>启动强>
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var builder = new ContainerBuilder();
builder.Register(c => c.CreateDbContextOptionsFor<DBContext1>("DBContext1")).As<DbContextOptions<DBContext1>>().SingleInstance();
builder.Register(c => c.CreateDbContextOptionsFor<DBContext2>("DBContext2")).As<DbContextOptions<DBContext2>>().SingleInstance();
builder.RegisterType<DBContext1>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<DBContext2>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<SomeComponent>().As<ISomeComponent>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).InstancePerLifetimeScope();
builder.Populate(services);
var container = builder.Build();
return new AutofacServiceProvider(container);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
....
}
}
CreateDbContextOptionsFor 帮助器实现。引入它是为了使Startup
代码简洁易读。通过使用autofac的参数化工厂而不是new DbContextOptionsBuilder<TContext>()
,可以进一步改进它,但我不确定在这种情况下是否存在点。
public static class DBExtentions
{
public static DbContextOptions<TContext> CreateDbContextOptionsFor<TContext>(this IComponentContext ctx,
string connectionName) where TContext : DbContext
{
var connectionString = ctx.Resolve<IConfiguration>().GetConnectionString(connectionName);
return new DbContextOptionsBuilder<TContext>().UseSqlServer(connectionString).Options;
}
}
<强>的UnitOfWork 强>
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : DbContext
{
private TContext _context;
public UnitOfWork(TContext context)
{
_context = context;
}
}
注射和使用工作单元
public class SomeComponent : ISomeComponent
{
private readonly IUnitOfWork<DBContext1> _uow;
public SomeComponent(IUnitOfWork<DBContext1> uow)
{
_uow = uow;
}
public void DoSomething()
{
_uow.DoWhatever();
}
....