一些备注和我的意见:
1)不应该只在 Product 类中使用类别 ID,并使用单独的产品类别存储库来加载类别。您正在使用 ORM(至少我假设您正在使用),以便能够通过类实例之间的引用来建模关系,而不是通过查询关系方式使用ID。将您的想法推到最后的结果意味着您完全从模型类中删除了所有导航属性,并且只有标量属性,其中一些作为对象之间的键。这只是ORM中的“R”。
2)目前,我的存储库接口实现返回一个扩展 Product 类型并通过存储库实例支持延迟加载的对象。不确定这确切意味着什么(我想看看您如何执行代码片段)。但我猜测在您派生的 Product 类中,您以某种方式注入了对存储库的引用,例如:
public class ProductProxy : Product
{
private IProductRepository _productRepo;
public ProductProxy(IProductRepository productRepo)
{
_productRepo = productRepo;
}
}
显然现在加载类别是一个问题,因为 IProductRepository
没有访问它们的方法。
3)
我想知道产品和类别存储库应该如何相互交互以实现延迟加载?它们应该相互引用还是我应该有一个主存储库,其中包含两个子存储库,并将其传递给我的扩展模型类型?
您的 ProductRepository 和 CategoryRepository 看起来像是通用存储库的实例,仅负责单个实体类型(在 EF 4.1 中,这类似于 DbSet<T>
,其中 T
分别为 Product
或 Category
)。
我建议避免这些存储库之间的引用,因为每当您添加新实体或导航属性时,这可能会导致复杂的 repo-references。
我看到另外两个选项:
(Basically what you already mentioned) Having a repository which is responsible for Product
and Category
together. You could still have your generic repositories but I would consider them more as internal helper repos and would only use them as private members inside of the main repository. This way you can have a group of repositories, each of them is responsible for some closely related entities.
Introduce a Unit of Work
which is able to create all of your generic repositories (again in EF 4.1 this would be something like the factory method DbContext.Set<T>()
where DbContext
is the unit of work) and then inject this Unit of Work into your derived instances:
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>();
}
set { ... }
}
}
我更倾向于第二个选项,因为在第一个选项中,您可能会最终需要支持加载所有可能的关系的大型存储库。考虑一下:订单有订单项,订单项有产品,产品有类别,订单有客户,客户有地址列表,地址有联系人列表等等...
4)(因为您也在寻求批评意见)
您是在编写自己的ORM还是编写应用程序?根据我的看法,您的设计走向可能变得非常复杂,并且您正在重新发明轮子。如果您计划使用EF或NHibernate(或其他ORM),则您正在创建已经提供了开箱即用的功能,您只需要在其上添加抽象,这并不增加任何价值。通过动态代理进行延迟加载在透明的情况下发生,您从未在代码中显式地使用这些代理,您始终使用您的POCO实体。它们是不可见的,仅在运行时存在。为什么要开发自己的延迟加载基础设施?