我有标准的Repository界面设置:
public interface IRepository<T, TKey> : IDisposable where T : class
{
T Get(TKey id);
IEnumerable<T> Get();
IEnumerable<T> Find(Expression<Func<T, bool>> whereClause);
T Add(T entity);
void Delete(T entity);
bool Save();
int Update(T entity);
}
并且有一个实现:
public class EfRepository<T, TKey> : IRepository<T, TKey> where T : class
{
protected DbContext _context;
public EfRepository(DbContext context) { ...}
public virtual T Get(TKey id) {...}
public virtual IEnumerable<T> Get() { ...}
public virtual IEnumerable<T> Find(Expression<Func<T, bool>> whereClause) { ...}
public T Add(T entity) { ...}
public void Delete(T entity) { ...}
public bool Save() { ...}
public int Update(T entity) { ...}
}
我在所有这些方面都有一个服务层:
public class VehicleService: IVehicleService
{
private readonly IRepository<Vehicle, int> _repository;
public VehicleService(IRepository<Vehicle, int> repository)
{
_repository = repository;
}
public IEnumerable<int> GetModelYears()
{
// ?? help?
}
}
我的问题是,在哪里实现一个Distinct方法? LINQ查询如下所示:
context.Set<Vehicle>().Select(x => x.ModelYear).Distinct();
我还没有弄清楚如何在存储库级别对一个Distinct方法进行一般编码,我认为这不是正确的地方。
我们选择不在我们的存储库中返回IQueryable。但我也没有将任何实际的DbSet对象暴露给服务层。
也许更好的问题是,这是一种正确的做事方式吗?还有更好的方法吗?
答案 0 :(得分:1)
这里有几个选项:
1)最有效的方法是执行
context.Set<Vehicle>().Select(x => x.ModelYear).Distinct();
存储库中的部分。您可能已经知道,这将确保sql查询在返回结果集之前在数据库级别执行distinct。这可确保不会从数据库返回大型数据集,只会使.Net进一步限制内存中的结果集。从那里,你将_vehicleService.GetModelYears调用_vehicleRepository.GetDistinctModelYears。
2)如果你正在处理一个非常小的数据集,并且在一个完整的行上执行内存中的Distinct功能所带来的性能损失并不重要,你可以: a)让你的GetModelYears()&#39; Service中的方法调用_vehicleRepository.GetVehicles()方法,然后b)对从存储库返回的车辆列表执行Distinct。
答案 1 :(得分:1)
如果这只是用于某种对象的东西,而不是用于存储库中的所有对象,那么你可以创建一个新的存储库,包含该查询,但是建立在IRepository上。
public interface IVehicleRepository : IRepository<Vehicle>{
IEnumerable<int> GetDistinctVehicle();
}
public VehicleRepository : EfRepository<Vehicle>, IVehicleRepository{
public VehicleRepository(DbContext context) : base(context)
{
}
public IEnumerable<int> GetDistinctVehicle(){
Context.Set<Vehicle>().Select(x=> x.ModelYear).Distinct();
}
}
通过这种方式,您仍然可以使用所有IRepositorystuff,也可以使用额外的方法。只需将IVehicleRepository绑定到您选择的注入器中的VehicleRepository,并将其注入构造函数,就像使用IRepositories一样。