После большого прочтения репозитория и Data Mapper я решил реализовать эти шаблоны в тестовом проекте. Поскольку я новичок в этом, я хотел бы узнать ваше мнение о том, как я реализовал их в простом проекте.
Джереми Миллер говорит:
Сделайте какой-нибудь нетривиальный проект персонального кодирования, где вы можете свободно экспериментировать с шаблонами проектирования.
Но я не знаю, правильно ли я все это сделал или нет.
Вот моя структура проекта:
Как вы можете видеть, есть много папок, которые я собираюсь подробно описать ниже.
Домен: доменные объекты проекта идут сюда. У меня есть простой класс Personnel, который унаследован от класса EntityBase, класс EntityBase имеет единственное свойство с именем Id.
public int Id { get; set; }
Инфраструктура: вот простой уровень доступа к данным с двумя классами. SqlDataLayer - это простой класс, который унаследован от абстрактного класса с именем DataLayer. Здесь я предоставляю некоторые функции, такие как следующий код:
public SQLDataLayer() {
const string connString = "ConnectionString goes here";
_connection = new SqlConnection(connString);
_command = _connection.CreateCommand();
}
добавление параметра в набор параметров команд:
public override void AddParameter(string key, string value) {
var parameter = _command.CreateParameter();
parameter.Value = value;
parameter.ParameterName = key;
_command.Parameters.Add(parameter);
}
выполнение DataReader:
public override IDataReader ExecuteReader() {
if (_connection.State == ConnectionState.Closed)
_connection.Open();
return _command.ExecuteReader();
}
и т. Д.
- Репозиторий: здесь я попытался реализовать шаблон репозитория. IRepository - универсальный интерфейс
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;
}
Я не выставлял не реализованные методы из IRepository.
Здесь, в классе Generic Repository, я ожидаю, что два параметра в конструкторе: во-первых, это ссылка на мой класс SqlDataLayer, а во-вторых, это ссылка на Entity DataMapper.
Эти параметры отправляются каждым классом репозитория сущностей, который унаследован от класса репозитория. например:
public class PersonnelRepository : Repository<Personnel>, IPersonnelRepository {
public PersonnelRepository(DataLayer domainContext, PersonnelDataMapper dataMapper)
: base(domainContext, dataMapper) {
}
}
Как вы можете видеть здесь, в методе FindOne я пытался автоматизировать некоторые операции, такие как создание CommandText, затем я воспользовался своим классом DataLayer, чтобы настроить команду и, наконец, выполнить команду для получения IDataReader. Я передаю IDataReader в свой класс DataMapper для сопоставления с сущностью.
DomainMapper: наконец, здесь я сопоставляю результат IDataReader с сущностями, ниже приведен пример того, как я сопоставляю сущность персонала:
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"])
};
}}
Использование:
using (var context = new SQLDataLayer()) {
_personnelRepository = new PersonnelRepository(context, new PersonnelDataMapper());
var personnel = _personnelRepository.FindOne(1);
}
Я знаю, что допустил много ошибок здесь, поэтому я здесь. Мне нужен ваш совет, чтобы узнать, что я сделал не так или каковы хорошие моменты в этом простом тестовом проекте.
Заранее спасибо.