Несколько замечаний и моих мнений:
1)
Должен ли я иметь только идентификатор категории в классе Product и использовать отдельныйхранилище для категорий товаров для загрузки категории?
Нет.Вы используете ORM (по крайней мере, я так полагаю), чтобы иметь возможность моделировать отношения по ссылкам между экземплярами классов, а не по идентификаторам, которые вы используете для запроса в реляционном режиме.Принятие вашей идеи к последнему следствию означало бы, что вы вообще удалили все свойства навигации из классов модели и имеете только скалярные свойства, а некоторые из них действуют как ключи между объектами.Это только "R" в ORM.
2)
На данный момент моя реализация интерфейса репозитория возвращает объект типа, который расширяет Productвведите и поддерживает отложенную загрузку через экземпляр репозитория.
Не уверен, что именно это означает.(Я хотел бы увидеть фрагмент кода, как вы это делаете.) Но я предполагаю, что в вашем производном Product
классе вы как-то вставляете ссылку на хранилище, например:
public class ProductProxy : Product
{
private IProductRepository _productRepo;
public ProductProxy(IProductRepository productRepo)
{
_productRepo = productRepo;
}
// now you use _productRepo to lazily load something on request, do you?
}
Хорошо, очевидно, сейчас проблема загрузки категорий, поскольку IProductRepository
не имеет методов для доступа к ним.
3)
Мне интереснокак должны взаимодействовать репозитории продуктов и категорий для достижения ленивой загрузки?Должны ли они ссылаться друг на друга или у меня должен быть основной репозиторий с двумя суб-репозиториями и передать его в мои расширенные типы моделей?
Ваш ProductRepository и CategoryRepository выглядят как экземпляры универсального репозитория, который отвечает толькодля одного типа сущности (в EF 4.1 это было бы похоже на DbSet<T>
, где T
равно Product
или Category
соответственно).
Я бы избегал ссылок между этими репозиториями, так как это можетзаканчивайте адом сложных репо-ссылок всякий раз, когда вы добавляете новые сущности или свойства навигации.
Я вижу два других варианта:
(в основном то, что вы уже упомянули)Наличие репозитория, который отвечает за Product
и Category
вместе.У вас все еще могут быть свои общие репозитории, но я бы больше рассматривал их как внутренние репозитории-помощники и использовал бы их только в качестве закрытых членов внутри основного репозитория.Таким образом, вы можете создать группу репозиториев, каждый из которых отвечает за несколько тесно связанных сущностей.
Введите Unit of Work
, который может создать все ваши общие репозитории (сновав EF 4.1 это было бы что-то вроде заводского метода DbContext.Set<T>()
, где DbContext
- единица работы), а затем вставьте эту единицу работы в ваши производные экземпляры:
public class ProductProxy : Product
{
private IUnitOfWork _unitOfWork;
public ProductProxy(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public Category Category
{
get
{
// ...
var productRepo = _unitOfWork.CreateGenericRepo<Product>();
var categoryRepo = _unitOfWork.CreateGenericRepo<Category>();
// you can pull out the repos you need and work with them
}
set { ... }
}
}
Я бы предпочел второй вариант, потому что в первом варианте вы можете оказаться в огромных репозиториях для поддержки загрузки всех возможных связей.Подумайте: у заказа есть элементы заказа, у элемента заказа есть продукт, у продукта есть категория, у клиента есть заказ, у клиента есть список адресов, у адреса есть список контактных лиц и т. Д. И т. Д. И т. Д. ...
4) (потому что вы также просили критиковать)
Вы пишете свой собственный ORM или вы пишете заявку?Ваш дизайн идет в направлении, которое может стать очень сложным, и вы, по моему мнению, изобретаете колесо заново.Если вы планируете использовать EF или NHibernate (или другие ORM), то вы создаете функции, которые уже доступны из коробки, вы только помещаете абстракции поверх них, которые не добавляют никакой ценности.Ленивая загрузка через динамические прокси происходит прозрачно в том смысле, что вы никогда не работаете явно с этими прокси в вашем коде, вы всегда работаете с вашими объектами POCO.Они невидимы и существуют только во время выполнения.Почему вы хотите разработать собственную инфраструктуру отложенной загрузки?