Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AutoFac/.NET核心-寄存器DBcontext_C#_.net Core_Autofac_Ef Core 2.0 - Fatal编程技术网

C# AutoFac/.NET核心-寄存器DBcontext

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

我有一个新的.NET核心Web API项目,该项目具有以下项目结构:

API->业务/域->基础架构

API非常精简,只有API方法。业务/域层拥有我的所有业务逻辑。最后,我的基础架构层使用EF Core 2.0创建了我的DB类

我知道使用.NET Core内置的依赖项注入,我可以将API项目的引用添加到基础设施项目中,然后在StartUp.cs文件中添加以下代码:

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();
}