在Repository Pattern中,我应该在哪里实现Distinct方法?

时间:2014-04-22 18:03:19

标签: c# entity-framework repository distinct

我有标准的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对象暴露给服务层。

也许更好的问题是,这是一种正确的做事方式吗?还有更好的方法吗?

2 个答案:

答案 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一样。