Шаблон репозитория против DAL
Это одно и то же? Только что закончили смотреть учебник Роберта Коннери на витрине магазина, и они, похоже, похожи на техники. Я имею в виду, что когда я реализую объект DAL, у меня есть методы GetStuff, Add/Delete и т. Д., И я всегда сначала пишу интерфейс, чтобы потом можно было переключать db.
Я что-то путаю?
11 ответов
Ты определенно не тот, кто путает вещи.:-)
Я думаю, что ответ на вопрос зависит от того, насколько пуристом вы хотите быть.
Если вам нужна строгая точка зрения DDD, это приведет вас к одному пути. Если вы посмотрите на репозиторий как на шаблон, который помог нам стандартизировать интерфейс уровня, который разделяет службы и базу данных, он перенесет вас на другой уровень.
Хранилище с моей точки зрения - это просто четко определенный уровень доступа к данным. Другими словами, стандартизированный способ реализации вашего уровня доступа к данным. Существуют некоторые различия между различными реализациями репозитория, но концепция одна и та же.
Некоторые люди будут накладывать дополнительные ограничения DDD на хранилище, в то время как другие будут использовать хранилище в качестве удобного посредника между базой данных и уровнем обслуживания. Репозиторий, такой как DAL, изолирует сервисный уровень от особенностей доступа к данным.
Одна из проблем реализации, которая, кажется, отличает их, заключается в том, что хранилище часто создается с помощью методов, которые принимают спецификацию. Репозиторий будет возвращать данные, которые удовлетворяют этой спецификации. Большинство традиционных DAL, которые я видел, будут иметь больший набор методов, где метод будет принимать любое количество параметров. Хотя это может показаться небольшой разницей, это большая проблема, когда вы входите в области Linq и Expressions. Наш интерфейс хранилища по умолчанию выглядит следующим образом:
public interface IRepository : IDisposable
{
T[] GetAll<T>();
T[] GetAll<T>(Expression<Func<T, bool>> filter);
T GetSingle<T>(Expression<Func<T, bool>> filter);
T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
void Delete<T>(T entity);
void Add<T>(T entity);
int SaveChanges();
DbTransaction BeginTransaction();
}
Это DAL или репозиторий? В этом случае я думаю, что оба.
Ким
Репозиторий - это шаблон, который можно применять различными способами, в то время как уровень доступа к данным несет очень четкую ответственность: DAL должен знать, как подключиться к вашему хранилищу данных для выполнения операций CRUD.
Хранилище может быть DAL, но оно также может находиться перед DAL и выступать в качестве моста между уровнем бизнес-объекта и уровнем данных. Какая реализация будет использоваться, будет варьироваться от проекта к проекту.
Одно большое отличие состоит в том, что DAO - это общий способ справиться с постоянством для любого объекта в вашем домене. С другой стороны, хранилище имеет дело только с совокупными корнями.
Я искал ответ на аналогичный вопрос и согласен с двумя наиболее высоко оцененными ответами. Пытаясь уточнить это для себя, я обнаружил, что если спецификации, которые идут рука об руку с шаблоном репозитория, реализуются как первоклассные члены модели предметной области, то я могу
- повторно использовать определения спецификации с различными параметрами,
- манипулировать параметрами существующих экземпляров Спецификации (например, специализироваться),
- объединить их,
- выполнять бизнес-логику на них без необходимости какого-либо доступа к базе данных,
- и, конечно, тестировать их независимо от реальных реализаций репозитория.
Я могу даже пойти так далеко и заявить, что, если шаблон Repository не используется вместе с шаблоном Specification, на самом деле это не "Repository", а DAL. Придуманный пример в псевдокоде:
specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)
assert that specification200.isSpecialCaseOf(specification100)
specificationAge = new AccountIsOlderThan('2000-01-01')
combinedSpec = new CompositeSpecification(
SpecificationOperator.And, specification200, specificationAge)
for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
assert that account.Created < '2000-01-01'
assert that account.Orders.Count > 200
Подробности смотрите в эссе Спецификации Фаулера (на этом я основывался выше).
DAL будет иметь специальные методы, такие как
IoCManager.InstanceFor<IAccountDAO>()
.GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')
Вы можете увидеть, как это может быстро стать громоздким, тем более что вам необходимо определить каждый из интерфейсов DAL/DAO с помощью этого подхода и реализовать метод запроса DAL.
В.NET запросы LINQ могут быть одним из способов реализации спецификаций, но объединение спецификаций (выражений) может быть не таким гладким, как с домашним решением. Некоторые идеи для этого описаны в этом вопросе.
Мое личное мнение таково, что все дело в картографировании, см. http://www.martinfowler.com/eaaCatalog/repository.html. Таким образом, вывод / ввод из хранилища являются объектами домена, которые в DAL могут быть чем угодно. Для меня это важное добавление / ограничение, так как вы можете добавить реализацию репозитория для базы данных / службы / чего угодно с другим макетом, и у вас есть четкое место, чтобы сконцентрироваться на выполнении сопоставления. Если бы вы не использовали это ограничение и не использовали отображение в другом месте, то наличие разных способов представления данных может повлиять на код в тех местах, где он не должен изменяться.
Преимущество использования шаблона репозитория заключается в том, что он позволяет имитировать уровень доступа к данным, чтобы вы могли тестировать код бизнес-уровня без вызова кода DAL. Есть и другие большие преимущества, но мне кажется, что это очень важно.
Все дело в интерпретации и контексте. Они могут быть очень похожими или даже очень разными, но пока решение работает, что в названии!
Репозиторий - это шаблон, это способ реализовать вещи стандартизированным способом повторного использования кода, как мы можем.
Во внешнем мире (то есть в клиентском коде) хранилище такое же, как и в DAL, за исключением:
(1) его методы вставки / обновления / удаления ограничены, чтобы иметь в качестве параметра объект контейнера данных.
(2) для операции чтения может потребоваться простая спецификация, такая как DAL (например, GetByPK) или расширенная спецификация.
Внутренне он работает с Data Mapper Layer (например, контекстом структуры объекта и т. Д.) Для выполнения фактической операции CRUD.
Какой шаблон репозитория не означает:-
Кроме того, я видел людей, которые часто путаются, когда используют отдельный метод Save в качестве примера реализации шаблона репозитория, кроме методов Insert/Update/Delete, которые фиксируют все изменения в памяти, выполняемые методами вставки / обновления / удаления, в базу данных. У нас может быть определенно метод Save в репозитории, но он не несет ответственности за репозиторий за изоляцию в памяти CUD (Create, Update, Delete) и методов персистентности (которые выполняют фактическую операцию записи / изменения в базе данных), но ответственность за единицу работы.
Надеюсь это поможет!
Можно утверждать, что "репозиторий" - это определенный класс, а "DAL" - это весь уровень, состоящий из репозиториев, DTO, служебных классов и всего остального, что требуется.
Таким образом, в большинстве (простых) случаев DAO является реализацией репозитория?
Насколько я понимаю, похоже, что DAO имеет дело именно с доступом к базе данных (CRUD - нет выбора, хотя?!), а репозиторий позволяет абстрагировать весь доступ к данным, возможно, являясь фасадом для нескольких DAO (может быть, разных источников данных).
Я на правильном пути?
Из того, что я понимаю, они могут означать в основном одно и то же - но наименование зависит от контекста.
Например, у вас может быть класс Dal/Dao, который реализует интерфейс IRepository.
Dal/Dao - термин уровня данных; более высокие уровни вашего приложения мыслят в терминах репозиториев.