Как обрабатывать отношения таблицы с шаблоном репозитория?

Я реализую шаблон репозитория как часть сайта ASP.NET MVC. Большинство примеров, которые я видел в репозиториях, довольно просты. Например, типичный абстрактный интерфейс репозитория.

public interface IRepository<TEntity>
{
    IQueryable<TEntity> All();
    TEntity FindBy(int id);
    TEntity FindBy(Expression<Func<TEntity, bool>> expression);
    IQueryable<TEntity> FilterBy(Expression<Func<TEntity, bool>> expression);
    bool Add(TEntity entity);
    bool Update(TEntity entity);
    bool Delete(TEntity entity):
}

Мне ясно, как использовать такой репозиторий для добавления, обновления, удаления или получения объектов одного типа. Но как вы справляетесь с созданием и управлением отношениями "один ко многим" или "многие ко многим" между разными типами?

Скажем, у вас есть тип Item, где каждому элементу присваивается Category. Как бы вы могли выполнить это задание через репозиторий? Должно ли это соответствовать методам Update(Category c) и/или Update(Item i), чтобы выяснить, какие отношения необходимо внести в обновляемый элемент или из него? Или должен быть явный метод AssignCategoryToItem(Item i, Category c)?

Если это имеет значение, я использую Fluent NHibernate для реализации моих конкретных репозиториев.

Ответ 1

Как ваше приложение обрабатывает присвоение категории элементу?

Это:

  • Позволяет пользователю просматривать элемент и назначать ему категорию
  • Позволяет пользователю просматривать категорию и добавлять к ней элементы.

Пусть ваше приложение определяет, какой метод вы выбираете.

Это воспитывает идею наличия слоя Business Logic/Services и имеет дело с совокупными корнями. В моих приложениях у меня всегда есть слой services, где находится вся бизнес-логика. Я обнаружил, что это упростило мое приложение для понимания и поддержки/рефакторинга. (Примечание. Я также использую общие репозитории и ставил сложные репозитарии в отдельные функции в соответствующем классе службы)

На вашем уровне services у вас будет функция под названием AssignCategoryToItem, которая затем примет категорию (совокупный корень), и вы добавите элемент к этому category и сохраните изменения - хотя я предпочтет передать в IDs категории и вытащить его из базы данных перед обновлением.

Ответ 2

После того, как вы определили свои совокупные корни, вы должны создать для них очень специфичные интерфейсы репозитория (например, IProductRepository), и их уровень обслуживания будет потреблять их.

Такие, как...

public interface IProductRepository
{
    IList<Product> GetProductsInCategory(Category c);
    Product GetProductBy(int id);
    IList<Category> GetActiveProductCategories();
}

Затем в вашей конкретной реализации IProductRepository вы будете использовать общий репозиторий и запрашивать связанные с ним объекты и присоединяться к ним по мере необходимости.