I am trying to follow this tutorial Repository pattern without ORM that looks promising and did the exact thing as in the tutorial. My plan is simple, just to retrieve data from the database:
Model:
public class TeamDetails
{
public int TeamId { get; set; }
public string TeamName { get; set; }
}
public class DataConnection
{
public string DefaultConnection { get; set; }
}
Ado Repository:
public abstract class AdoRepository<T> where T : class
{
private static SqlConnection _connection;
string connectionString = "Data Source=.;Initial Catalog=DemoApp;Trusted_Connection=True";
public AdoRepository(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
public virtual T PopulateRecord(SqlDataReader reader)
{
return null;
}
protected List<T> GetRecords(SqlCommand command)
{
var list = new List<T>();
command.Connection = _connection;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
list.Add(PopulateRecord(reader));
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
finally
{
_connection.Close();
}
return list;
}
protected T GetRecord(SqlCommand command)
{
T record = null;
command.Connection = _connection;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
{
record = PopulateRecord(reader);
break;
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
finally
{
_connection.Close();
}
return record;
}
protected IEnumerable<T> ExecuteStoredProc(SqlCommand command)
{
var list = new List<T>();
command.Connection = _connection;
command.CommandType = CommandType.StoredProcedure;
_connection.Open();
try
{
var reader = command.ExecuteReader();
try
{
while (reader.Read())
{
var record = PopulateRecord(reader);
if (record != null) list.Add(record);
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
finally
{
_connection.Close();
}
return list;
}
}
Interface:
public interface ITeam
{
List<TeamDetails> GetAllTeams();
}
Implementing the team repository:
public class TeamRepository : AdoRepository<TeamDetails>, ITeam
{
public TeamRepository(string connectionString)
: base(connectionString)
{
}
public List<TeamDetails> GetAllTeams()
{
using (var command = new SqlCommand("select * from Team"))
{
return GetRecords(command);
}
}
public override TeamDetails PopulateRecord(SqlDataReader reader)
{
return new TeamDetails
{
TeamId = Convert.ToInt32(reader.GetString(0)),
TeamName = reader.GetString(1)
};
}
}
A service interface:
public interface ITeamRepoService
{
List<TeamDetails> GetAllTeams();
}
Implementing the service:
public class ITeamService : ITeamRepoService
{
private readonly ITeam _repository;
public ITeamService(IOptions<DataConnection> options)
{
var connection = options.Value;
_repository = new TeamRepository(connection.DefaultConnection);
}
public List<TeamDetails> GetAllTeams()
{
return _repository.GetAllTeams();
}
}
Finally calling it in the controller as follows:
private readonly ITeamService _service;
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger, ITeamService service)
{
_logger = logger;
_service = service;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<TeamDetails>>> Index()
{
var teams = _service.GetAllTeams();
return Ok(teams);
}
The issue is when I run the code, it throws an exception from the Startup.cs file:
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: TodoApi.Interface.ITeam Lifetime: Scoped ImplementationType: TodoApi.Repository.TeamRepository': Unable to resolve service for type 'System.String' while attempting to activate 'TodoApi.Repository.TeamRepository'.)
In the start up file, I did the following but didn't work out:
services.Configure<DataConnection>(Configuration.GetSection("AppDbConnection"));
services.AddTransient<ITeamRepoService, ITeamService>();
services.AddTransient<ITeam, TeamRepository>();
Any way to resolve it?
CodePudding user response:
As what @juunas said, your TeamRepository expects a string(connectionString
), change your code below:
services.AddTransient<ITeam, TeamRepository>(_ => new TeamRepository("connectionString here"));
Reference: