我正在应用程序中实现仓储模式,并遇到了两个模式理解上的“问题”:
查询 - 我读到IQueryable在使用仓储时不应使用。然而,显然你希望这样做,以便每次调用方法时都不返回完整的对象列表。它应该被实现吗?如果我有一个名为List的IEnumerable方法,则IQueryable的一般“最佳实践”是什么?应该/不应该具有哪些参数?
标量值 - 从使用仓储模式的角度来看,如何返回一个单一的标量值,而不必返回整个记录?从性能的角度来看,仅返回单个标量值是否更有效率?
我正在应用程序中实现仓储模式,并遇到了两个模式理解上的“问题”:
查询 - 我读到IQueryable在使用仓储时不应使用。然而,显然你希望这样做,以便每次调用方法时都不返回完整的对象列表。它应该被实现吗?如果我有一个名为List的IEnumerable方法,则IQueryable的一般“最佳实践”是什么?应该/不应该具有哪些参数?
标量值 - 从使用仓储模式的角度来看,如何返回一个单一的标量值,而不必返回整个记录?从性能的角度来看,仅返回单个标量值是否更有效率?
严格来说,仓库(Repository)提供了获取/存储领域对象的集合语义。它为您的材料化实现(ORM、手动编写、模拟)提供了一个抽象,以便领域对象的消费者与这些细节解耦。在实践中,仓库通常抽象访问实体,即具有标识和持久生命周期的领域对象。在DDD风格中,仓库提供对聚合根的访问。
仓库的最小接口如下:
void Add(T entity);
void Remove(T entity);
T GetById(object id);
IEnumerable<T> Find(Specification spec);
虽然你会看到命名差异以及Save/SaveOrUpdate语义的添加,但以上是“纯粹”的想法。你可以获得ICollection Add/Remove成员以及一些查找器。如果你不使用IQueryable,你还将在存储库上看到查找方法,如:
FindCustomersHavingOrders();
FindCustomersHavingPremiumStatus();
Add(T entity);
Remove(T entity);
T GetById(object id);
IQueryable<T> Find();
当查询需求增加时,您可以放弃所有这些自定义的Finder方法,这真的会使存储库变得混乱。
interface ICanAdd<T>
{
T Add(T entity);
}
interface ICanRemove<T>
{
bool Remove(T entity);
}
interface ICanGetById<T>
{
T Get(int id);
}
interface ISomeRepository
: ICanAdd<SomeClass>,
ICanRemove<SomeClass>
{
SomeClass Add(SomeClass entity);
bool Remove(SomeClass entity);
}