Эта небольшая заметка является ответом на публикацию «Проблемный шаблон Repository».
Все основные идеи для приведенного ниже примера слоя Persistance / Repository для взяты из этой статьи. Этот код лишь частичной подкорректирован под потребности используемой мною архитектуры. Предлагаемое решение настолько простое, логичное и универсальное, что не могу его не привести после чтения статьи Александра.
Аналогичный подход для java-приложений хорошо описан здесь.
1. Рассмотрим слой Persistance, который состоит из 2х подслоёв — фабрики баз данных и репозитория данных.
2. Пример вызова методов репозитория в слое бизнес-логики
3. Также можно вообще кардинально упростить код напрямую используя класс DpdRepository<...>
Все основные идеи для приведенного ниже примера слоя Persistance / Repository для взяты из этой статьи. Этот код лишь частичной подкорректирован под потребности используемой мною архитектуры. Предлагаемое решение настолько простое, логичное и универсальное, что не могу его не привести после чтения статьи Александра.
Аналогичный подход для java-приложений хорошо описан здесь.
1. Рассмотрим слой Persistance, который состоит из 2х подслоёв — фабрики баз данных и репозитория данных.
/// <summary> базовый интерфейс для подслоя фабрики баз данных </summary>
public interface IDatabaseFactory
{
/// <summary>Контекст базы данных (технология linq2sql)</summary>
DataContext Get();
}
/// <summary> интерфейс для работы с базой данных Dpd </summary>
public interface IDpdDatabaseFactory : IDatabaseFactory
{
}
/// <summary>
/// Класс который фактически является обёрткой над DataContext нужной нам базы данных
/// </summary>
public class DpdDatabaseFactory : IDpdDatabaseFactory, IDisposable
{
/// <summary>Контекст конкретной базы данных (технология linq2sql)</summary>
private DpdDataContext context;
/// <summary>Получение контекста базы данных</summary>
public DataContext Get()
{
if (context == null)
{
context = new DpdDataContext();
}
return context;
}
public void Dispose()
{
if (context != null)
{
context.Dispose();
}
}
}
/// <summary> базовый интерфейс для подслоя репозитория </summary>
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
T Get(Expression<Func<T, Boolean>> where);
IEnumerable<T> GetAll();
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
}
/// <summary> базовый класс для подслоя репозитория </summary>
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
/// <summary>Контекст бд</summary>
protected DataContext context;
/// <summary>таблицы с сущностями бд</summary>
protected Table<TEntity> table;
public BaseRepository(IDatabaseFactory dbFactory)
{
context = dbFactory.Get();
table = context.GetTable<TEntity>();
}
public virtual void Add(TEntity entity)
{
if (entity != null)
{
table.InsertOnSubmit(entity);
}
}
public virtual void Delete(TEntity entity)
{
if (entity != null)
{
table.DeleteOnSubmit(entity);
}
}
public virtual TEntity Get(Expression<Func<TEntity, bool>> where)
{
return table.Where(where).FirstOrDefault();
}
public virtual IEnumerable<TEntity> GetMany(Expression<Func<TEntity, bool>> where)
{
return table.Where(where);
}
public virtual IEnumerable<TEntity> GetAll()
{
return table;
}
}
/// <summary> репозиторий объектов бд Dpd </summary>
public class DpdRepository<TEntity> : BaseRepository<TEntity> where TEntity : class
{
/// <summary>
/// При помощи механизма фреймворка IoC получаем экземпляр этого класса
/// (а в него вложен экземпляр DataContext нужной нам бд) с необходимым временем жизни
/// Например со временем жизна Http запроса
/// </summary>
public DpdRepository() : base(UnityInstance.Container.Resolve<IDpdDatabaseFactory>())
{
}
public DpdDataContext Context
{
get
{
var rprContext = (DpdDataContext) context;
return rprContext;
}
}
}
/// <summary>создаём репозиторий для конкретного типа сущности модели домена </summary>
public class ProjectRepository : DpdRepository<Project>
{
}
2. Пример вызова методов репозитория в слое бизнес-логики
var repository = new ProjectRepository();
var list = repository.GetMany(item => item.parent_project_id == ProjectId).ToList();
3. Также можно вообще кардинально упростить код напрямую используя класс DpdRepository<...>
var list = (new DpdRepository<Project>()).GetMany(item => item.parent_project_id == ProjectId).ToList();