Home > Back-end >  Problem with inclusion data access layer in DI container
Problem with inclusion data access layer in DI container

Time:10-26

So, there is a problem when i start include my dependencies in DI container. I have a data access library of my database. And when i try to add this in DI container it fails in app.build statement with 3 exceptions related to the same errors. Exceptions:

! System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: DAL.Repos.Interfaces.ICarRepo Lifetime: Scoped ImplementationType: DAL.Repos.CarRepo': Unable to activate type 'DAL.Repos.CarRepo'. The following constructors are ambiguous: Void .ctor(DAL.EfMainStructures.ApplicationContext) Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions`1[DAL.EfMainStructures.ApplicationContext]))

! System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: DAL.Repos.Interfaces.ICarRepo Lifetime: Scoped ImplementationType: DAL.Repos.CarRepo': Unable to activate type 'DAL.Repos.CarRepo'. The following constructors are ambiguous: Void .ctor(DAL.EfMainStructures.ApplicationContext) Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions`1[DAL.EfMainStructures.ApplicationContext])

! System.InvalidOperationException: Unable to activate type 'DAL.Repos.CarRepo'. The following constructors are ambiguous: Void .ctor(DAL.EfMainStructures.ApplicationContext) Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions`1[DAL.EfMainStructures.ApplicationContext])

All of them are related to constructors ambiguous, but i can't understand what it means. This my Program.cs code

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
// Add services to the container.
 var connectionString = builder.Configuration.GetConnectionString("Default");
 builder.Services.AddDbContextPool<ApplicationContext>(options => 
     options.UseNpgsql(connectionString,sqlOp =>
         sqlOp.EnableRetryOnFailure()));
 builder.Services.AddScoped<ICarRepo,CarRepo>(); 
 /*builder.Services.AddScoped<ICustomerRepo,CustomerRepo>();
 builder.Services.AddScoped<ICreditRiskRepo,CreditRiskRepo>();
 builder.Services.AddScoped<IMakeRepo,MakeRepo>();
 builder.Services.AddScoped<IOrderRepo,OrderRepo>();*/
 
 /*builder.Services.AddScoped(typeof(IAppLogging<>),typeof(AppLogging<>));
builder.Host.ConfigureSerilog();*/

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    if (app.Configuration.GetValue<bool>("RebuildDataBase"))
    {
        var context = new DatabaseContextFactory().CreateDbContext(new string[1]);
        SampleDataInitializer.InitializeData(context);
    }

    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

This my ApplicationContext code

public partial class ApplicationContext : DbContext
{
    public ApplicationContext(DbContextOptions<ApplicationContext> options)
        : base(options)
    {
        
    }
    public virtual DbSet<CreditRisk>? CreditRisks { get; set; }
    public virtual DbSet<Customer>? Customers { get; set; }
    public virtual DbSet<Make>? Makes { get; set; }
    public virtual DbSet<Car>? Cars { get; set; }
    public virtual DbSet<Order>? Orders { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        OnModelCreatingPartial(modelBuilder);
    }
    partial void OnModelCreatingPartial(ModelBuilder modelBuilder); 
}

This GitHub repository: https://github.com/DIDIVERG/Train (There considered MVC project)

It has to add my interfaces with their implementations to DI container, but it doesn't and throws exceptions described above. I'm sorry if this question is hackneyed.

CodePudding user response:

Based on the provided error message DAL.Repos.CarRepo has two constructors with one parameter, so the DI is not able to determine which one to use. Remove one of the constructors.

CodePudding user response:

The important piece of code is your CarRepo, which is in a dependency not included in your Git Repo.

It looks like it has two public constructors, and the DI container is able to provide the parameters for both, hence it cannot decide which constructor it should use and reports 'ambiguous'.

My guess is your CarRepo has the following:

public CarRepo(ApplicationContext context)
{
}

public CarRepo(DbContextOptions<ApplicationContext> options)
{
}

In a repo, you should only need the first one. The DbContextOptions are used when the DI container instantiates the ApplicationContext.

CodePudding user response:

As others mentioned, DI container is unable to decide which constructor to use. One option to solve it is to explicitly tell it which one to use by providing a factory method:

builder.Services.AddScoped<ICarRepo>(
    sp => new CarRepo(sp.GetRequiredService<YourClassDependencyHere>()));

I am not a fan of such approach as it would require updating each time constructor signature changes, but it is a simple fix.

  • Related