英文:
Some services are not able to be constructed === When I tend to build my API
问题
I have models:
public class Employees
{
public int Id { get; set; }
public string First_name { get; set; }
public string Last_name { get; set; }
public string User_name { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone_number { get; set; }
public string Mobile_number { get; set; }
public bool Active_is { get; set; }
}
public class HasRole
{
public int Id { get; set; }
public int Employees_id { get; set; }
public int Role_id { get; set; }
public TimeOnly Time_from { get; set; }
public TimeOnly Time_to { get; set; }
public bool Active_is { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Role_name { get; set; }
}
I have IRepository:
public interface IRepository<TEntity>
{
Task<IEnumerable<TEntity>> Get_all_Information();
Task<TEntity> Get_by_Id(int id);
}
and Implementation:
public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
protected IDbConnection _connection;
protected IDbTransaction _transaction;
protected string title_table;
public RepositoryBase(IDbConnection connection, IDbTransaction transaction, string titleTable)
{
_connection = connection;
_transaction = transaction;
title_table = titleTable;
}
public async Task<IEnumerable<TEntity>> Get_all_Information()
{
var query = $"Select * From {title_table}";
return await _connection.QueryAsync<TEntity>(query, transaction: _transaction);
}
public async Task<TEntity> Get_by_Id(int id)
{
string query = $"Select * From {title_table} Where Id = @id";
var result =
await _connection.QueryFirstOrDefaultAsync<TEntity>(query, param: new { id }, transaction: _transaction);
if (result == null)
{
throw new KeyNotFoundException($"{title_table} with id [{id}] could not be found.");
}
return result;
}
}
Employee Repository:
public class EmployeesRepository : RepositoryBase<Employees>, IEmployeesRepository
{
public EmployeesRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction, "Employees")
{
}
public async Task<IEnumerable<Employees>> Get_all_activity_Employees()
{
string query = "Select * From [dbo].Employees Where Active_is = 1";
IEnumerable<Employees> result = await _connection.QueryAsync<Employees>(query, transaction: _transaction);
return result;
}
public async Task<IEnumerable<Employees>> Get_all_Employees_By_Specialization(string specialization)
{
string query = "Select a.First_name, a.Last_name, b.Role_name " +
"From Employees a, Role b, Has_Role c " +
$"Where c.Employees_id = a.Id and c.Role_id = b.Id and b.Role_name = {specialization}";
IEnumerable<Employees> result = await _connection.QueryAsync<Employees>(query, transaction: _transaction);
return result;
}
}
I add Scoped to DI
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(s =>
{
s.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Swagger Example-Dapper-Migration API",
Description = "Base Swagger Description"
});
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
s.IncludeXmlComments(xmlPath);
});
builder.Services.AddScoped((s) => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
builder.Services.AddScoped<IDbTransaction>(s =>
{
SqlConnection connection = s.GetRequiredService<SqlConnection>();
connection.Open();
return connection.BeginTransaction();
});
// Dependency Injections
builder.Services.AddSingleton<DapperContext>()
.AddScoped<ICompanyRepository, CompanyRepository>()
.AddScoped<IDepartmentRepository, DepartmentRepository>()
.AddScoped<IEmployeesRepository, EmployeesRepository>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(s =>
{
s.SwaggerEndpoint("/swagger/v1/swagger.json", "Swagger API Version");
s.RoutePrefix = string.Empty;
});
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
and I have the Problem:
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Dapper_Data_Access_Layer.Repository.Contracts.Interfaces.IEmployeesRepository Lifetime: Scoped ImplementationType: Dapper_Data_Access_Layer.Repository.Contracts.EmployeesRepository': Unable to resolve service for type 'System.Data.IDbConnection' while attempting to activate 'Dapper_Data_Access_Layer.Repository.Contracts.EmployeesRepository'.)'
I create the RoleRepository and HasRoleRepository, but I have the same problem. I only start learning it, and maybe my mistake is very simple, but I will be very grateful for the help.
英文:
I have models:
public class Employees
{
public int Id { get; set; }
public string First_name { get; set; }
public string Last_name { get; set; }
public string User_name { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone_number { get; set; }
public string Mobile_number { get; set; }
public bool Active_is { get; set; }
}
public class HasRole
{
public int Id { get; set; }
public int Employees_id { get; set; }
public int Role_id { get; set; }
public TimeOnly Time_from { get; set; }
public TimeOnly Time_to { get; set; }
public bool Active_is { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Role_name { get; set; }
}
I have IRepository:
public interface IRepository<TEntity>
{
public Task<IEnumerable<TEntity>> Get_all_Information();
public Task<TEntity> Get_by_Id(int id);
}
and Implementation:
public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
protected IDbConnection _connection;
protected IDbTransaction _transaction;
protected string title_table;
public RepositoryBase(IDbConnection connection, IDbTransaction transaction, string titleTable)
{
_connection = connection;
_transaction = transaction;
title_table = titleTable;
}
public async Task<IEnumerable<TEntity>> Get_all_Information()
{
var query = $"Select * From {title_table}";
return await _connection.QueryAsync<TEntity>(query, transaction: _transaction);
}
public async Task<TEntity> Get_by_Id(int id)
{
string query = $"Select * From {title_table} Where Id = @id";
var result =
await _connection.QueryFirstOrDefaultAsync<TEntity>(query, param: new { id }, transaction: _transaction);
if (result == null)
{
throw new KeyNotFoundException($"{title_table} with id [{id}] could not be found.");
}
return result;
}
}
Employee Repository:
public class EmployeesRepository : RepositoryBase<Employees>, IEmployeesRepository
{
public EmployeesRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction, "Employees")
{
}
public async Task<IEnumerable<Employees>> Get_all_activity_Employees()
{
string query = "Select * From [dbo].Employees Where Active_is = 1";
IEnumerable<Employees> result = await _connection.QueryAsync<Employees>(query, transaction: _transaction);
return result;
}
public async Task<IEnumerable<Employees>> Get_all_Employees_By_Specialization(string specialization)
{
string query = "Select a.First_name, a.Last_name, b.Role_name " +
"From Employees a, Role b, Has_Role c " +
$"Where c.Employees_id = a.Id and c.Role_id = b.Id and b.Role_name = {specialization}";
IEnumerable<Employees> result = await _connection.QueryAsync<Employees>(query, transaction: _transaction);
return result;
}
}
I add Scoped to DI
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(s =>
{
s.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Swagger Example-Dapper-Migration API",
Description = "Base Swagger Description"
});
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
s.IncludeXmlComments(xmlPath);
});
builder.Services.AddScoped((s) => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
builder.Services.AddScoped<IDbTransaction>(s =>
{
SqlConnection connection = s.GetRequiredService<SqlConnection>();
connection.Open();
return connection.BeginTransaction();
});
// Dependency Injections
builder.Services.AddSingleton<DapperContext>()
.AddScoped<ICompanyRepository, CompanyRepository>()
.AddScoped<IDepartmentRepository, DepartmentRepository>()
.AddScoped<IEmployeesRepository, EmployeesRepository>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(s =>
{
s.SwaggerEndpoint("/swagger/v1/swagger.json", "Swagger API Version");
s.RoutePrefix = string.Empty;
});
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
and I have the Problem:
> System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Dapper_Data_Access_Layer.Repository.Contracts.Interfaces.IEmployeesRepository Lifetime: Scoped ImplementationType: Dapper_Data_Access_Layer.Repository.Contracts.EmployeesRepository': Unable to resolve service for type 'System.Data.IDbConnection' while attempting to activate 'Dapper_Data_Access_Layer.Repository.Contracts.EmployeesRepository'.)'
I create the RoleRepository and HasRoleRepositroy, but I have the same problem. I only start learning it and maybe my mistake is very simple, but I will be very grateful for the help
答案1
得分: 1
您的异常消息表示存储库找不到已注册的 IDbConnection
实现。可能的原因是内置的 IoC 没有将您的 SqlConnection
映射到 IDbConnection
。
builder.Services.AddScoped((s) => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
因此,尝试显式注册它:
builder.Services.AddScoped<IDbConnection>(s => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
请确保通过检查 IServicesCollection
进行注册。
更新:
我已下载您的项目并重新检查了代码。答案似乎是正确的 - 我尝试显式注册 IDbConnection
,并且它已为 EmployeesRepository
构建,然而在 DepartmentRepository
中出现了类似的问题,因为您在那里等待 SqlConnection
。
解决方案有两个:
1 - 在所有地方使用相同的参数(SqlConnection
或 IDbConnection
)进行注入
或者
2 - 注册 both SqlConnection
和 IDbConnection
(这不是一个好的方法)
另外,请记住,如果选择仅使用 IDbConnection
,它可能在运行时失败,因为在这里使用 IDbConnection
会导致以下行失败,因为在集合中没有 SqlConnection
服务:
builder.Services.AddScoped<IDbTransaction>(s =>
{
// 下面的行将失败,因为集合中没有 SqlConnection 服务
// 也在这里使用 IDbConnection
SqlConnection connection = s.GetRequiredService<SqlConnection>();
connection.Open();
return connection.BeginTransaction();
});
英文:
Your exception message says that Repository cannot find the registered IDbConnection
implementation. The possible reason is that built-in IoC didn't map your SqlConnection
to the IDbConnection
.
> builder.Services.AddScoped((s) => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
Therefore, try to register it explicitly:
builder.Services.AddScoped<IDbConnection>(s => new SqlConnection(builder.Configuration.GetConnectionString("SqlConnection")));
Make sure it is registered by checking IServicesCollection
.
UPD:
I downloaded your project and rechecked the code. The answer seems to be right - I tried to register IDbConnection
explicitly and it has been built for EmployeesRepository
, however the similar issue appeared for DepartmentRepository
as you wait for SqlConnection
there.
The solutions are:
1 - Use the same parameter everywhere (SqlConnection
or IDbConnection
) for injections
OR
2 - Register both SqlConnection
and IDbConnection
(which is not good approach)
Also keep in mind, that if you choose to use IDbConnection
only, it might fail in runtime over here:
builder.Services.AddScoped<IDbTransaction>(s =>
{
// line below will fail as there is no SqlConnection service in the Collection
// Use IDbConnection here as well
SqlConnection connection = s.GetRequiredService<SqlConnection>();
connection.Open();
return connection.BeginTransaction();
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论