Шаблон репозитория и свойства навигации - PullRequest
7 голосов
/ 14 марта 2011

Я просто хочу знать лучшие практики по написанию методов репозитория.Проблема в том, чтобы решить написать репозиторий, в котором нет отложенной загрузки.Как вы называете свой метод, если это GetById, но не ясно, какие навигационные элементы включены в сущность.

Так что я думаю написать имена методов, такие как GetUserByIdIncludedPosts Или лучше использовать активированный контекст с отложенной загрузкой?

Если я напишу включенные свойства в именах методов, это будет очень раздражать длинные имена методов для нескольких свойств навигации.

Ответы [ 2 ]

2 голосов
/ 14 марта 2011

Я использую следующее в своем базовом классе репозитория, чтобы разрешить поиск сущностей вместе с указанным пользователем списком зависимостей / отношений:

protected DbSet<T> Objects { get; private set; }
protected YourDatabaseContext Context { get; private set; }

public virtual T GetByID( int id, params string[] children )
{
    if( children == null || children.Length == 0 )
    {
        return Objects.SingleOrDefault( e => e.ID == id );
    }
    DbQuery<T> query = children.Aggregate<string, DbQuery<T>>( Objects, ( current, child ) => current.Include( child ) );
    return query.SingleOrDefault( e => e.ID == id );
}

Код использует EF4 / CTP5 и, следовательно, использует классы Db *, но тривиален для преобразования обратно в обычные классы EF4 (например, ObjectSet вместо DbSet).

Это будет использоваться так:

var product = productsRepository.GetByID( 42, "Category", "Orders.OrderLines" );

, который доставит вам товар с заполненными категориями и заказами, а также все заказы с загруженными линиями заказов.

2 голосов
/ 14 марта 2011

Использование шаблона репозитория не означает, что вы не сможете использовать отложенную загрузку.Вы все еще можете вернуть сущность, которая сможет лениво загружать связанные сущности.Единственное требование состоит в том, что DbContext используемый для загрузки объекта должен быть "живым".

Но давайте посмотрим на определение хранилища по Мартин Фаулер :

Репозиторий является посредником между доменом и слоями отображения данных, действуя какколлекция объектов домена памяти.Объекты клиента создают декларативные спецификации запросов и отправляют их в хранилище для удовлетворения.Объекты могут добавляться и удаляться из репозитория, как и из простой коллекции объектов, и код отображения, инкапсулированный репозиторием, будет выполнять соответствующие операции за кулисами.Концептуально репозиторий инкапсулирует набор объектов, сохраняемых в хранилище данных, и операции, выполняемые над ними, обеспечивая более объектно-ориентированное представление уровня персистентности.Хранилище также поддерживает цель достижения четкого разделения и односторонней зависимости между доменом и слоями отображения данных.

Я думаю, что интересная часть состоит в следующем: Клиентские объекты создают спецификации запросов декларативно и отправляютих в хранилище для удовлетворения .Также хранилище обычно используется для обеспечения совокупных корней.Таким образом, вы либо всегда будете предоставлять весь корень (не всегда возможно), либо вы будете удовлетворять упомянутому утверждению, и вы определите нетерпеливую загрузку вне хранилища с помощью Include метода расширения для IQueryable.Поэтому вам никогда не понадобятся специализированные методы, такие как GetUserByIdIncludeSomething.

Если вы хотите, чтобы пользовательское хранилище начиналось с этого метода для всех запросов:

public interface IRepository<T>
{
  IQueryable<T> GetQuery();
}

Кстати.Я не думаю, что пользователь является совокупным корнем для сообщений.В этом случае большинство приложений будет иметь только один сводный корень - пользователь.

Редактировать:

Небольшое уточнение: IQueryable по умолчанию не обеспечивает Include метод.Он предоставляется как метод расширения в сборке CTP5, но если вы используете его, вы сделаете свой верхний уровень зависимым от EntityFramework.dll.Это то, что вы обычно не хотите (причина, по которой вы используете хранилище).Таким образом, вам нужно определить собственный метод расширения, добавив расширение в сборку с вашим хранилищем.

...