Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务“ApplicationDbContext”尚未注册

问题描述 投票:0回答:1

我在启动应用程序时收到错误:

尝试连接数据库时发生错误。(Myproj.Web.Program) Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务“Myproj.Infrastruct.Data.ApplicationDbContext”尚未注册。要避免此异常,请注册一个组件来提供服务,使用 IsRegistered() 检查服务注册,或者使用 ResolveOptional() 方法来解析可选依赖项。 在 Autofac.ResolutionExtensions.ResolveService(IComponentContext 上下文、Service 服务、IEnumerable

1 parameters) at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable
1 个参数) 在 Autofac.ResolutionExtensions.Resolve(IComponentContext 上下文,类型 serviceType) 在 Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(类型 serviceType) 在 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider 提供程序,类型 serviceType) 在 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider 提供程序) 在 C:\proj\myproj\src\Myproj.Web\Program.cs 中的 Myproj.Web.Program.Main(String[] args):第 45 行

这是我的Program.cs

public class Program
{
    public static bool DatabaseUnavailable = false;
    public static void Main(string[] args)
    {
        CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");

        var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
        Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(config).CreateLogger();

        try
        {
            Log.Information("MyProg Application Starting Up");

            var host = CreateHostBuilder(args).Build();

            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;

                try
                {
                    var context = services.GetRequiredService<ApplicationDbContext>(); // ERROR

似乎当应用程序尝试从 IoC 容器(本例中为 Autofac)解析

ApplicationDbContext
时,它找不到它。这可能是因为它没有正确注册,或者注册被覆盖或丢失。

这是代码:

  1. Program.cs:这是错误的根源,特别是在:
var context = services.GetRequiredService<ApplicationDbContext>();

程序尝试从 DI 容器获取

ApplicationDbContext
的实例,但由于未注册而失败。

  1. StartupSetup.cs:这是将
    ApplicationDbContext
    添加到
    IServiceCollection
    的位置。
public static class StartupSetup
{
    public static void AddDbContext(this IServiceCollection services, string connectionString) =>
        services.AddDbContext<ApplicationDbContext>(options =>
        {
            options.UseSqlServer(connectionString,
                providerOptions =>
                {
                    providerOptions
                        .EnableRetryOnFailure(
                            maxRetryCount: 5, 
                            maxRetryDelay: TimeSpan.FromSeconds(30),
                            errorNumbersToAdd: null)
                        .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
                });
            options.EnableSensitiveDataLogging();

    // ... rest of the code
  1. Startup.cs:这是配置服务的地方,检查
    AddDbContext
    是否正确调用至关重要。我打过电话:
string connectionString = Configuration.GetConnectionString("MyWebApp");
services.AddDbContext(connectionString);

这应该将

ApplicationDbContext
添加到
IServiceCollection
。但是,这并不能保证它已在 Autofac 中注册。

  1. Program.cs 和 Startup.cs:我使用 Autofac 作为 DI 容器,并且有一些特定配置将 Autofac 与 ASP.NET Core 集成:
.UseServiceProviderFactory(new AutofacServiceProviderFactory())

Startup.cs

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterModule(new DefaultInfrastructureModule(_env.EnvironmentName == "Development",
        Assembly.GetExecutingAssembly()));
    // ... rest of the code
}

如何确保

ApplicationDbContext
也在 Autofac 的
ContainerBuilder
中正确注册?

Autofac 模块定义如下:

public class DefaultInfrastructureModule : Module
    {
        private readonly bool _isDevelopment = false;
        private readonly List<Assembly> _assemblies = new List<Assembly>();

        public DefaultInfrastructureModule(bool isDevelopment, Assembly callingAssembly = null)
        {
            _isDevelopment = isDevelopment;
            var coreAssembly = Assembly.GetAssembly(typeof(IUserResolverService));
            var infrastructureAssembly = Assembly.GetAssembly(typeof(Repository));
            _assemblies.Add(coreAssembly);
            _assemblies.Add(infrastructureAssembly);
            if (callingAssembly != null)
            {
                _assemblies.Add(callingAssembly);
            }
        }

        protected override void Load(ContainerBuilder builder)
        {
            if (_isDevelopment)
            {
                RegisterDevelopmentOnlyDependencies(builder);
            }
            else
            {
                RegisterProductionOnlyDependencies(builder);
            }
            RegisterCommonDependencies(builder);
        }

        private void RegisterCommonDependencies(ContainerBuilder builder)
        {
            //var infrastructureAssembly = Assembly.GetAssembly(typeof(EfRepository));
            builder
                .RegisterAssemblyTypes(_assemblies.ToArray())
                .PublicOnly()
                .Where(t =>
                t.Name.EndsWith("Repository") ||
                t.Name.EndsWith("Factory") ||
                t.Name.EndsWith("Service") ||
                t.Name.EndsWith("Generator") ||
                false
                )
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
            //builder.RegisterType<EfRepository>().As<IRepository>()
            //    .InstancePerLifetimeScope();

            builder
                .RegisterType<HttpContextAccessor>()
                .As<IHttpContextAccessor>()
                .SingleInstance();

            builder
                .RegisterType<Mediator>()
                .As<IMediator>()
                .InstancePerLifetimeScope();

            builder.Register<ServiceFactory>(context =>
            {
                var c = context.Resolve<IComponentContext>();
                return t => c.Resolve(t);
            });

            var mediatrOpenTypes = new[]
            {
                typeof(IRequestHandler<,>),
                typeof(IRequestExceptionHandler<,,>),
                typeof(IRequestExceptionAction<,>),
                typeof(INotificationHandler<>),
            };

            foreach (var mediatrOpenType in mediatrOpenTypes)
            {
                builder
                .RegisterAssemblyTypes(_assemblies.ToArray())
                .AsClosedTypesOf(mediatrOpenType)
                .AsImplementedInterfaces();
            }

            builder.RegisterType<EmailSender>().As<IEmailSender>()
                .InstancePerLifetimeScope();
        }

        private void RegisterDevelopmentOnlyDependencies(ContainerBuilder builder)
        {
            // TODO: Add development only services
        }

        private void RegisterProductionOnlyDependencies(ContainerBuilder builder)
        {
            // TODO: Add production only services
        }

    }
c# asp.net-core autofac .net-5 dbcontext
1个回答
0
投票

最终还是手动注册了DbContext

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterModule(new DefaultInfrastructureModule(_env.EnvironmentName == "Development",
        Assembly.GetExecutingAssembly()));

    // added this
    builder.RegisterType<ApplicationDbContext>().InstancePerLifetimeScope();

错误消失了

© www.soinside.com 2019 - 2024. All rights reserved.