我正在考虑两个IRepository接口中的一个,一个是IQueryable的后代,另一个是IQueryable。
像这样:
public interface IRepository<T> : IQueryable<T>
{
T Save(T entity);
void Delete(T entity);
}
或者这个:
public interface IRepository<T>
{
T Save(T entity);
void Delete(T entity);
IQueryable<T> Query();
}
LINQ用法是:
from dos
in ServiceLocator.Current.GetInstance<IRepository<DomainObject>>()
where dos.Id == id
select dos
或者...
from dos
in ServiceLocator.Current.GetInstance<IRepository<DomainObject>>().Query
where dos.Id == id
select dos
我有点像第一个,但是模拟是有问题的。其他人如何实现LINQable,可模拟的存储库?
答案 0 :(得分:14)
取决于您是否需要Has-A或Is-A关系。
第一个是Is-A关系。 IRepository接口是一个IQueryable接口。第二个是a-a。 IRepository具有IQueryable接口。在写这篇文章的过程中,我实际上喜欢第二个比第一个好,只是因为当使用你的第二个IRepository时,我可以给出返回IQueryable的Query()方法ANYTHING。对我来说,这比第一次实施更灵活。
答案 1 :(得分:8)
就个人而言,我使用Repository Pattern
将所有项目从存储库返回为IQueryable
。通过这样做,我的存储库层现在非常轻,小..使用服务层(使用存储库层)现在可以对所有类型的查询操作开放。
基本上,我的所有逻辑现在都位于服务层(它不知道它将使用什么类型的存储库......并且不想知道&lt; - 关注点的分离)..而我的存储库层只是处理获取数据和保存数据到repo(一个sql服务器,一个文件,一个太空卫星......等等 - 更多的关注点分离)。
例如。或多或少的pseduo代码,因为我记得我们在代码中做了什么,并简化了这个答案......
public interface IRepository<T>
{
IQueryable<T> Find();
void Save(T entity);
void Delete(T entity);
}
并拥有一个用户存储库......
public class UserRepository : IRepository<User>
{
public IQueryable<User> Find()
{
// Context is some Entity Framework context or
// Linq-to-Sql or NHib or an Xml file, etc...
// I didn't bother adding this, to this example code.
return context.Users().AsQueryable();
}
// ... etc
}
现在是最好的一点:)
public void UserServices : IUserServices
{
private readonly IRepository<User> _userRepository;
public UserServices(IRepository<User> userRepository)
{
_userRepository = userRepository;
}
public User FindById(int userId)
{
return _userRepository.Find()
.WithUserId(userId)
.SingleOrDefault(); // <-- This will be null, if the
// user doesn't exist
// in the repository.
}
// Note: some people might not want the FindBySingle method because this
// uber method can do that, also. But i wanted to show u the power
// of having the Repository return an IQuerable.
public User FindSingle(Expression<Func<User, bool>> predicate)
{
return _userRepository
.Find()
.SingleOrDefault(predicate);
}
}
加分点:WithUserId(userId)
方法中的WTF为FindById
?那是Pipe and Filter。使用它们:)爱他们:)拥抱他们:)他们使你的代码SOOO更具可读性:)现在,如果你想知道那是做什么..这是扩展方法。
public static User WithId(this IQueryable<User> source, int userId)
{
return source.Where(u => u.UserId == userId).SingleOrDefault();
}
HTH即使这个问题是......好吧......差不多两年了:)
答案 2 :(得分:0)
你总是可以快速写一些针对List的东西,它不是嘲笑使用模拟框架,但它确实很有效。