After a lots of read about Repository and Data Mapper I decided to implement those patterns in a test project. Since I'm new to these I'd like to get your views about how did I implement those in a simple project.
Jeremy Miller says :
Do some sort of nontrivial, personal coding project where you can freely experiment with design patterns.
But I don't know I did all this things right or not.
Here is my project structure :
As you can see there are many folders which I'm going to describe them in detail in below.
Domain : Project Domain Entities go here I've a simple Personnel class which is inherited from EntityBase class, EntityBase class has a single property named Id.
public int Id { get; set; }
Infrustructure : Here is a simple Data Access Layer with two classes. SqlDataLayer is a simple class which is inherited from an abstract class named DataLayer. Here I provide some functionality like following code :
public SQLDataLayer() { const string connString = "ConnectionString goes here"; _connection = new SqlConnection(connString); _command = _connection.CreateCommand(); }
adding parameter to commands parameter collection :
public override void AddParameter(string key, string value) {
var parameter = _command.CreateParameter();
parameter.Value = value;
parameter.ParameterName = key;
_command.Parameters.Add(parameter);
}
executing DataReader :
public override IDataReader ExecuteReader() {
if (_connection.State == ConnectionState.Closed)
_connection.Open();
return _command.ExecuteReader();
}
and so on.
- Repository : Here I tried to implement repository pattern. IRepository is a generic interface
IRepository.cs :
public interface IRepository<TEntity> where TEntity : EntityBase
{
DataLayer Context { get; }
TEntity FindOne(int id);
ICollection<TEntity> FindAll();
void Delete(TEntity entity);
void Insert(TEntity entity);
void Update(TEntity entity);
}
Repository.cs :
public class Repository<TEntity> : IRepository<TEntity> where TEntity : EntityBase, new() {
private readonly DataLayer _domainContext;
private readonly DataMapper<TEntity> _dataMapper;
public Repository(DataLayer domainContext, DataMapper<TEntity> dataMapper) {
_domainContext = domainContext;
_dataMapper = dataMapper;
}
public DataLayer Context {
get { return _domainContext; }
}
public TEntity FindOne(int id)
{
var commandText = AutoCommand.CommandTextBuilder<TEntity>(CommandType.StoredProcedure, MethodType.FindOne);
// Initialize parameter and their types
Context.AddParameter("Id", id.ToString(CultureInfo.InvariantCulture));
Context.SetCommandType(CommandType.StoredProcedure);
Context.SetCommandText(commandText);
var dbReader = Context.ExecuteReader();
return dbReader.Read() ? _dataMapper.Map(dbReader) : null;
}
I didn't expose not implemented methods from IRepository.
Here in Generic Repository class I expect two parameters in constructor first is a reference to my SqlDataLayer class and second is a reference to Entity DataMapper. Those parameters sent by each Entities Repository class which inherited from Repository class. for example :
public class PersonnelRepository : Repository<Personnel>, IPersonnelRepository {
public PersonnelRepository(DataLayer domainContext, PersonnelDataMapper dataMapper)
: base(domainContext, dataMapper) {
}
}
As you can see here in the FindOne method I tried to automate some operation such as creating CommandText, then I took the advantage of my DataLayer class to configure command and finally execute command to get IDataReader. I pass IDataReader to my DataMapper class to map to the Entity.
DomainMapper : Finally here I map result of IDataReader to Entities, bellow is a sample of how I map Personnel entity :
public class PersonnelDataMapper : DataMapper<Personnel> { public override Personnel Map(IDataRecord record) { return new Personnel { FirstName = record["FirstName"].ToString(), LastName = record["LastName"].ToString(), Address = record["Address"].ToString(), Id = Convert.ToInt32(record["Id"]) }; }}
Usage :
using (var context = new SQLDataLayer()) {
_personnelRepository = new PersonnelRepository(context, new PersonnelDataMapper());
var personnel = _personnelRepository.FindOne(1);
}
I know I did many mistake here, that's why I'm here. I need your advice to know what I did wrong or what are the good points in this simple test project.
Thanks in advance.
DataLayer
class (possibly posting some code)? – Replete