我在启动应用程序时收到错误:
尝试连接数据库时发生错误。(Myproj.Web.Program) Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务“Myproj.Infrastruct.Data.ApplicationDbContext”尚未注册。要避免此异常,请注册一个组件来提供服务,使用 IsRegistered() 检查服务注册,或者使用 ResolveOptional() 方法来解析可选依赖项。 在 Autofac.ResolutionExtensions.ResolveService(IComponentContext 上下文、Service 服务、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 行1 parameters) at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable
这是我的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
时,它找不到它。这可能是因为它没有正确注册,或者注册被覆盖或丢失。
这是代码:
var context = services.GetRequiredService<ApplicationDbContext>();
程序尝试从 DI 容器获取
ApplicationDbContext
的实例,但由于未注册而失败。
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
AddDbContext
是否正确调用至关重要。我打过电话:string connectionString = Configuration.GetConnectionString("MyWebApp");
services.AddDbContext(connectionString);
这应该将
ApplicationDbContext
添加到 IServiceCollection
。但是,这并不能保证它已在 Autofac 中注册。
.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
}
}
最终还是手动注册了DbContext
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new DefaultInfrastructureModule(_env.EnvironmentName == "Development",
Assembly.GetExecutingAssembly()));
// added this
builder.RegisterType<ApplicationDbContext>().InstancePerLifetimeScope();
错误消失了