开发者

Expose a repository as an IQueryable

开发者 https://www.devze.com 2023-01-06 22:37 出处:网络
I\'d like to expose a Repository as an \'IQueryable\' type. The repository uses Linq to NHibernate to communicate with the database.

I'd like to expose a Repository as an 'IQueryable' type.

The repository uses Linq to NHibernate to communicate with the database.

Can anyone point me at an example implementation?

For example, what would the corresponding 'GetEnumerator()' implementation on my repository look like?

Edit:

Would something like this be appropriate?

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


    IEnumerator IEnumerable.GetEnumerator(开发者_如何转开发)
    {
        return ((IEnumerable<MyType>)this).GetEnumerator();
    }

}


This is a bad design.

An IQueryable is a question (lookup "query" in a dictionary). It's how you ask for data. It's what you should be giving to the Repository.

A Repository should be returning answers -- the data itself.

If the Repository is returning a IQueryable, you've pretty much negated the need for the Repository.


I think a Repository can give you 1 or more IQueryables/IEnumerables, but not : a Repository is an IQueryable.

It could look like:

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

    // more...
 }

You could return IQueryable<Person> from GetAllPerson() but that may not be an improvement. IEnumerable is simpler, less coupling.


Lots of opinions of this one, but Ayende (Oren Eini) seems to think IQueryable is ok to return and articulates his point rather well.


Just return session.Linq<T>()


I can see two possible solutions here:

  1. Expose IEnumerable and use .AsQueryable() when needed

    // 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. Accept expression in Repository method

    // 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();
    }
    

Note: Not any expression filter can be translated to SQL Query by Entity Framework

0

精彩评论

暂无评论...
验证码 换一张
取 消