I have an error when inject IRequestHandler
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler2[TabpediaFin.Handler.UnitMeasures.UnitMeasureList+Query,System.Collections.Generic.IEnumerable
1[TabpediaFin.Dto.UnitMeasureDto]] Lifetime: Transient ImplementationType: TabpediaFin.Handler.UnitMeasures.UnitMeasureList+QueryHandler': Unable to resolve service for type 'System.Data.IDbConnection' while attempting to activate 'TabpediaFin.Handler.UnitMeasures.UnitMeasureList+QueryHandler'.)'
DbManager.cs
using Npgsql;
namespace TabpediaFin.Infrastructure.Data;
public class DbManager
{
private readonly string _connectionString;
public DbManager(IConfiguration config)
{
_connectionString = config.GetConnectionString("DefaultConnection") ?? string.Empty;
}
public string ConnectionString => _connectionString;
public IDbConnection CreateConnection()
{
IDbConnection cn = new NpgsqlConnection(_connectionString);
DefaultTypeMap.MatchNamesWithUnderscores = true;
// SimpleCRUD.SetDialect(SimpleCRUD.Dialect.PostgreSQL);
return cn;
}
}
Program.cs
using FluentValidation.AspNetCore;
using Serilog;
using Serilog.Sinks.SystemConsole.Themes;
using System.Reflection;
using TabpediaFin.Infrastructure.Data;
using MediatR;
using TabpediaFin.Infrastructure.Validation;
using TabpediaFin.Infrastructure;
using Microsoft.AspNetCore.Builder;
using TabpediaFin.Infrastructure.OpenApi;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using TabpediaFin.Infrastructure.Migrator;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Npgsql;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Console(
outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}",
theme: AnsiConsoleTheme.Code)
.CreateBootstrapLogger();
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
builder.Services.AddMediatR(Assembly.GetExecutingAssembly());
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>));
builder.Services.AddDbMigrator();
builder.Services.AddDbContext<FinContext>();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.RegisterSwagger("Tabpedia Finance", "v1");
builder.Services.AddControllers(options =>
{
options.Filters.Add<ValidateModelFilter>();
})
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddCors();
builder.Services.RegisterSettings(builder.Configuration);
builder.Services.RegisterServices();
builder.Services.RegisterRepositories();
//builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(Configuration.GetConnectionString("AppConnectionString")));
builder.Services.AddJwt();
var app = builder.Build();
app.UseMiddlewares();
// Configure the HTTP request pipeline.
// if (app.Environment.IsDevelopment())
// {
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Tabpedia Finance v1"));
// }
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(
builder =>
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders("Token-Expired"));
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
TabpediaFin.Infrastructure.Migrator.Startup.UpdateDatabase(scope.ServiceProvider);
}
app.Run();
UnitMeasureList.cs
using Microsoft.EntityFrameworkCore;
namespace TabpediaFin.Handler.UnitMeasures
{
public class UnitMeasureList
{
public class Query : IRequest<IEnumerable<UnitMeasureDto>>
{ }
public class QueryHandler : IRequestHandler<Query, IEnumerable<UnitMeasureDto>>
{
private readonly IDbConnection _dbConnection;
private readonly ICurrentUser _currentUser;
public QueryHandler(
IDbConnection connection,
ICurrentUser currentUser)
{
_dbConnection = connection;
_currentUser = currentUser;
}
public async Task<IEnumerable<UnitMeasureDto>> Handle(Query req, CancellationToken cancellationToken)
{
string sql = $@"SELECT
um.*, at.Id, au.Id
FROM UnitMeasure um
INNER JOIN AppTenant at ON at.Id = um.Id
INNER JOIN AppUser au ON au.Id = um.Id ";
var unitMeasure = await _dbConnection.QueryAsync<UnitMeasureDto>(sql, new {
userName = _currentUser.Username
});
return unitMeasure.ToList();
}
}
}
}
UnitMeasureDto.cs
namespace TabpediaFin.Dto
{
public class UnitMeasureDto
{
protected UnitMeasureDto(
int id
,int tenantId
,string name
,string description
,int createdUid
,DateTime createdUtc
,int updatedUid
,DateTime updatedUtc
)
{
Id = id;
TenantId = tenantId;
Name = name;
Description = description;
CreatedUid = createdUid;
CreatedUtc = createdUtc;
UpdatedUid = updatedUid;
UpdatedUtc = updatedUtc;
}
public int Id { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int CreatedUid { get; set; }
public DateTime CreatedUtc { get; set; }
public int UpdatedUid { get; set; }
public DateTime UpdatedUtc { get; set; }
}
}
UnitMeasuresController.cs
namespace TabpediaFin.Handler.UnitMeasures
{
[Route("api/[controller]")]
[ApiController]
public class UnitMeasuresController : ControllerBase
{
private readonly IMediator _mediator;
public UnitMeasuresController(
IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
public async Task<IEnumerable<UnitMeasureDto>> Get() => await _mediator.Send(new UnitMeasureList.Query());
}
}
In Program.cs I changed this line
//builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(Configuration.GetConnectionString("AppConnectionString")));
to this
builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(builder.Configuration.GetConnectionString("AppConnectionString")));