我正在考虑两个IRepository接口中的一个,一个是IQueryable的后代,另一个是IQueryable.
像这样:
public interface IRepository<T> : IQueryable<T>
{
T Save(T entity);
void Delete(T entity);
}
Run Code Online (Sandbox Code Playgroud)
或这个:
public interface IRepository<T>
{
T Save(T entity);
void Delete(T entity);
IQueryable<T> Query();
}
Run Code Online (Sandbox Code Playgroud)
LINQ用法是:
from dos
in ServiceLocator.Current.GetInstance<IRepository<DomainObject>>()
where dos.Id == id
select dos
Run Code Online (Sandbox Code Playgroud)
要么...
from dos
in ServiceLocator.Current.GetInstance<IRepository<DomainObject>>().Query
where dos.Id == id
select dos
Run Code Online (Sandbox Code Playgroud)
我有点像第一个,但是模拟是有问题的.其他人如何实现LINQable,可模拟的存储库?
我是Repository Pattern的新手,在网上做了很多阅读之后,我对正在发生的事情有了大致的了解,但似乎存在想法冲突.
一个是IRepository应该返回的内容.
我想处理ONLY Pocos所以我会为每个聚合根提供一个IRepository实现,如下所示:
public class OrangeRepository: IOrangeRepository
{
public Orange GetOrange(IOrangeCriteria criteria);
}
Run Code Online (Sandbox Code Playgroud)
其中IOrangeCriteria采用了许多特定于查找Orange的参数.
我的另一件事是一些数据后端 - 这就是我首先进入这种模式的原因.我想我会为每个实现一个实现,例如
OrangeRepositoryOracle,OrangeRepositorySQL,OrangeRepositoryMock等
我想保持它开放,以便我可以使用EF或NHibernate - 再次,如果我的IOrangeRepository处理POCO然后我会通过实现OrangeRepositoryNHibernate等将其封装在Repository本身中.
我在正确的路线上吗?
谢谢
编辑:感谢您的反馈,我没有其他任何人在此刻反弹这些想法,所以感谢!
序言:
我的核心问题与此非常类似:如何在不将IQueryable暴露给我的应用程序的其余部分的情况下编写一个干净的存储库?一直没有答案.我希望如果我以不同的方式解决问题,并提出一个稍微不同的问题,我可能会得到一个结果.我将重复这个问题的一些内容,以避免要求读者阅读上下文.
问题:
我正在使用POCO实体和实体框架4.我试图在应用层允许对实体集进行复杂的ad-hoc过滤,同时试图避免暴露在IQueryable<T>我的存储库边界之外.这让我有些困难.
我不想在存储库上创建一个带有大量参数的单个大规模过滤器方法,例如:
IEnumerable GetFilteredCustomers(string nameFilter, string addressFilter, bool isActive, int customerId, ...)
Run Code Online (Sandbox Code Playgroud)
这不仅非常麻烦,而且看起来非常难看,特别是如果它主要是一堆零点等等.它也不像我想的那样可维护.
我不想在存储库上创建大量的过滤方法,例如:
IEnumerable GetActiveCustomers()
IEnumerable GetCustomersByName()
Run Code Online (Sandbox Code Playgroud)
这种方法存在许多问题,包括需要大量的方法列表,n!如果我希望能够以任意方式组合它们,那么n就是可用过滤条件的数量.(即所有名为George的活跃客户).也很难维护.
我不想创建可操作的可链接方法(Fluent Interface)IEnumerable<T>,因为最终需要从数据库中返回一个巨大的结果集并将其过滤到内存中,这不是一个可扩展的解决方案.
我无法创建一个操作的Fluent界面,IQueryable<T>因为正如我已经说过的,我不想暴露IQueryable<T>过去的存储库.
我想避免简单地通过传入一个充满参数而不是大参数列表的对象来重复单个大规模过滤方法,尽管此时这可能是最不丑的解决方案.
想法:
最终,我认为一个理想的解决方案是发现一些方法来创建一个不知道源的完整查询,并将其存储为参数.然后我可以将其传递到知道源的存储库中,并将查询应用于源并返回结果.
澄清; 与上面提到的简单地创建参数对象相反,我想使用原始LINQ查询,但是以某种方式将它们存储在变量中,并稍后将它们应用于数据源.我怀疑返回类型必须提前知道,但我完全可以定义并事先知道它.
要从另一个角度查看它,请考虑以下事项:
IQueryable<Customer> filteredCustomers = customerRepository.GetAll()
.Where(c => c.FirstName == "Dave")
.Where(c => c.IsActive == true)
.Where(c => c.HasAddress == true)
;
Run Code Online (Sandbox Code Playgroud)
我想将三个Where子句打包为一个查询对象,与customerRepository.GetAll()完全分开,将其作为参数传递并稍后应用.