将存储库公开为IQueryable

时间:2010-07-14 13:44:11

标签: c# .net linq iqueryable

我想将Repository暴露为'IQueryable'类型。

存储库使用Linq到NHibernate与数据库进行通信。

有人能指出我的示例实现吗?

例如,我的存储库中相应的'GetEnumerator()'实现是什么样的?

修改

这样的事情是否恰当?

public class MyTypeRepository : IEnumerable<MyType>
{        
    IEnumerator<MyType> IEnumerable<MyType>.GetEnumerator()
    {
        return Session.Linq<MyType>().GetEnumerator();
    }


    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable<MyType>)this).GetEnumerator();
    }

}

5 个答案:

答案 0 :(得分:4)

我认为存储库可以为您提供 1个或更多IQueryables / IEnumerables,但不是:存储库 是IQueryable。

它可能看起来像:

 public interface IPersonRepository
 {
    IEnumerable<Person> GetAllPersons();
    void AddPerson(Person person);

    // more...
 }

你可以从GetAllPerson()返回IQeryable<Person>,但这可能不是一个改进。 IEnumerable更简单,耦合更少。

答案 1 :(得分:4)

这是一个糟糕的设计。

IQueryable是一个问题(在字典中查找“查询”)。这就是你要求数据的方式。这就是你应该提供给存储库。

存储库应该返回答案 - 数据本身。

如果Repository返回了IQueryable,那么你几乎不需要存储库。

答案 2 :(得分:2)

对这一点有很多意见,但Ayende (Oren Eini)似乎认为IQueryable is ok要回归并清楚表达他的观点。

答案 3 :(得分:1)

只需返回session.Linq<T>()

答案 4 :(得分:1)

我可以在这里看到两种可能的解决方案:

  1. 公开IEnumerable并在需要时使用.AsQueryable()

    // Repository
    public IEnumerable<Person> GetAll() {
        return _dbContext.People.AsQueryable();
    }
    
    // Usage
    public Person GetByPhone(string phoneNumber) {
        var queryablePeople = _personRepository.GetAll().AsQueryable();
        return queryablePeople.FirstOrDefault(perspn => person.Phone == phoneNumber);
    }
    
  2. 使用存储库方法接受表达式

    // Repository
    public IEnumerable<Person> GetPeople(Expression<Func<Person, bool>> filter) {
        return _dbContext.People.Where(filter);
    }
    
    // Usage
    public Person GetByPhone(string phoneNumber) {
        return _personRepository.GetPeople(person => person.Phone == phoneNumber).FirstOrDefault();
    }
    

注意:实体框架不能将任何表达式过滤器转换为SQL查询