C# AutoFac/.NET核心-寄存器DBcontext
我有一个新的.NET核心Web API项目,该项目具有以下项目结构: API->业务/域->基础架构 API非常精简,只有API方法。业务/域层拥有我的所有业务逻辑。最后,我的基础架构层使用EF Core 2.0创建了我的DB类 我知道使用.NET Core内置的依赖项注入,我可以将API项目的引用添加到基础设施项目中,然后在StartUp.cs文件中添加以下代码:C# AutoFac/.NET核心-寄存器DBcontext,c#,.net-core,autofac,ef-core-2.0,C#,.net Core,Autofac,Ef Core 2.0,我有一个新的.NET核心Web API项目,该项目具有以下项目结构: API->业务/域->基础架构 API非常精简,只有API方法。业务/域层拥有我的所有业务逻辑。最后,我的基础架构层使用EF Core 2.0创建了我的DB类 我知道使用.NET Core内置的依赖项注入,我可以将API项目的引用添加到基础设施项目中,然后在StartUp.cs文件中添加以下代码: services.AddDbContext<MyContext>(options => options.UseS
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
services.AddDbContext(options=>options.UseSqlServer(connectionString));
然而,我想保持一种更传统的关注点分离。到目前为止,我已在我的基础结构层中添加了一个模块,该模块尝试进行如下注册:
builder.Register(c =>
{
var config = c.Resolve<IConfiguration>();
var opt = new DbContextOptionsBuilder<MyContext>();
opt.UseSqlServer(config.GetSection("ConnectionStrings:MyConnection:ConnectionString").Value);
return new MyContext(opt.Options);
}).AsImplementedInterfaces().InstancePerLifetimeScope();
builder.Register(c=>
{
var config=c.Resolve();
var opt=new DbContextOptionsBuilder();
opt.UseSqlServer(config.GetSection(“ConnectionString:MyConnection:ConnectionString”).Value);
返回新的MyContext(opt.Options);
}).AsImplementedInterfaces().InstancePerLifetimeScope();
但是,DBContext未注册。任何试图访问注入的DBContext的类都无法解析该参数
在.NET Core Web API项目中使用AuftoFac有没有办法在单独的项目中注册DBContext?在所需的项目中,您可以创建一个扩展方法,将上下文添加到集合中
public static class MyDataExtensions {
public static IServiceCollection AddMyData(this IServiceCollection services) {
//...
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
//...
}
}
API项目是合成根,因此它无论如何都需要知道所有相关的依赖项。至少在这个扩展中,您不必直接引用所使用的db上下文,我认为问题在于您试图使用
AsImplementedInterfaces()注册MyContext()
。DbContext通常不是这样注册的。您应该注册并解析类本身。我使用Autofac注册HttpContextAccessor
和DbContext
builder
.RegisterType<HttpContextAccessor>()
.As<IHttpContextAccessor>()
.SingleInstance();
builder
.RegisterType<AppDbContext>()
.WithParameter("options", DbContextOptionsFactory.Get())
.InstancePerLifetimeScope();
builder
.RegisterType()
.As()
.SingleInstance();
建设者
.RegisterType()
.WithParameter(“选项”,DbContextOptionsFactory.Get())
.InstancePerLifetimeScope();
dbcontextoptions工厂
public class DbContextOptionsFactory
{
public static DbContextOptions<AppDbContext> Get()
{
var configuration = AppConfigurations.Get(
WebContentDirectoryFinder.CalculateContentRootFolder());
var builder = new DbContextOptionsBuilder<AppDbContext>();
DbContextConfigurer.Configure(
builder,
configuration.GetConnectionString(
AppConsts.ConnectionStringName));
return builder.Options;
}
}
公共类DBContextOptions工厂
{
公共静态DbContextOptions Get()
{
var configuration=AppConfigurations.Get(
WebContentDirectoryFinder.CalculateContentRootFolder());
var builder=new DbContextOptionsBuilder();
DbContextConfigurer.Configure(
建设者
configuration.GetConnectionString(
AppConsts.ConnectionStringName);
返回builder.Options;
}
}
DbContextConfigurer
public class DbContextConfigurer
{
public static void Configure(
DbContextOptionsBuilder<AppDbContext> builder,
string connectionString)
{
builder.UseNpgsql(connectionString).UseLazyLoadingProxies();
}
}
公共类DbContextConfigurer
{
公共静态无效配置(
DbContextOptionsBuilder,
字符串连接(字符串)
{
UseNpgsql(connectionString.UseLazyLoadingProxies();
}
}
Autofac 4.8.1版的另一个简单解决方案
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ConnectionStrings:MyConnection:ConnectionString")));
var builder = new ContainerBuilder();
builder.Populate(services);
//...
// Your interface registration
//...
builder.Build(Autofac.Builder.ContainerBuildOptions.None);
}
public void配置服务(IServiceCollection服务)
{
services.AddMvc().addControllerAsservices();
services.AddDbContext(options=>options.UseSqlServer(Configuration.GetConnectionString(“ConnectionString:MyConnection:ConnectionString”));
var builder=new ContainerBuilder();
建造商。填充(服务);
//...
//您的界面注册
//...
builder.Build(Autofac.builder.ContainerBuildOptions.None);
}
我使用了一个实现——它模仿Autofac 4.9.4。确保根据您的要求调整范围
public void RegisterContext<TContext>(ContainerBuilder builder)
where TContext : DbContext
{
builder.Register(componentContext =>
{
var serviceProvider = componentContext.Resolve<IServiceProvider>();
var configuration = componentContext.Resolve<IConfiguration>();
var dbContextOptions = new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>());
var optionsBuilder = new DbContextOptionsBuilder<TContext>(dbContextOptions)
.UseApplicationServiceProvider(serviceProvider)
.UseSqlServer(configuration.GetConnectionString("MyConnectionString"),
serverOptions => serverOptions.EnableRetryOnFailure(5, TimeSpan.FromSeconds(30), null));
return optionsBuilder.Options;
}).As<DbContextOptions<TContext>>()
.InstancePerLifetimeScope();
builder.Register(context => context.Resolve<DbContextOptions<TContext>>())
.As<DbContextOptions>()
.InstancePerLifetimeScope();
builder.RegisterType<TContext>()
.AsSelf()
.InstancePerLifetimeScope();
}
public void register上下文(ContainerBuilder-builder)
其中TContext:DbContext
{
builder.Register(componentContext=>
{
var serviceProvider=componentContext.Resolve();
var配置=componentContext.Resolve();
var dbContextOptions=newdbcontextoptions(newdictionary());
var optionsBuilder=new DbContextOptionsBuilder(dbContextOptions)
.UseApplicationServiceProvider(服务提供者)
.UseSqlServer(configuration.GetConnectionString(“MyConnectionString”),
serverOptions=>serverOptions.EnableRetryOnFailure(5,TimeSpan.FromSeconds(30),null));
返回选项生成器。选项;
}).As()
.InstancePerLifetimeScope();
builder.Register(context=>context.Resolve())
.As()
.InstancePerLifetimeScope();
builder.RegisterType()
.AsSelf()
.InstancePerLifetimeScope();
}
另外,供将来参考。“然而,这不起作用。”-这不能解释任何事情,也不能帮助我们理解您的问题,所以我们必须猜测您的问题是什么。你应该写下到底发生了什么-错误消息,抛出异常,或者你所说的“这不起作用”是什么意思。它可能会使您的操作系统崩溃、关闭计算机或炸毁发电站——我们对此一无所知,因此无法提供有意义的建议。@AlexanderLeonov感谢您的反馈。我用更多的信息更新了问题。这样更好。看起来我的猜测是正确的-您应该直接注册MyContext类,而不是它实现的接口。您是正确的。我将.AsImplementedInterfaces()更改为.AsSelf(),现在它可以工作了。谢谢如果我想根据请求查询字符串更改连接字符串。如何访问HttpContext
内部dbcontextoptions工厂
类?我无法解析HttpContextAccessor
内部DbContextOptionsFactory
,因为它在我们访问DbContextOptionsFactory
时没有生成。
public void RegisterContext<TContext>(ContainerBuilder builder)
where TContext : DbContext
{
builder.Register(componentContext =>
{
var serviceProvider = componentContext.Resolve<IServiceProvider>();
var configuration = componentContext.Resolve<IConfiguration>();
var dbContextOptions = new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>());
var optionsBuilder = new DbContextOptionsBuilder<TContext>(dbContextOptions)
.UseApplicationServiceProvider(serviceProvider)
.UseSqlServer(configuration.GetConnectionString("MyConnectionString"),
serverOptions => serverOptions.EnableRetryOnFailure(5, TimeSpan.FromSeconds(30), null));
return optionsBuilder.Options;
}).As<DbContextOptions<TContext>>()
.InstancePerLifetimeScope();
builder.Register(context => context.Resolve<DbContextOptions<TContext>>())
.As<DbContextOptions>()
.InstancePerLifetimeScope();
builder.RegisterType<TContext>()
.AsSelf()
.InstancePerLifetimeScope();
}