Returning IQueryable<T>
Since LINQ was added to the .Net Community as a new wonderful new player, more and more solutions I have seen returns the IQueryable<T> from the Data Access Layer. One reason is to easy create different kind of queries in an easy way and execute them. Some developers use the IQueryable<T> interface to create a light weight interface for the Data Access Layer. It's an interesting solution, but at the moment I don't like it.
If we look at how developers uses the IQueryable<T>, we often see code like this:
public class CustomerRepository/CustomerDAL
public IQueryable<Customer> GetCustomers()
What is wrong with this code?
1) The GetCustomers method is lying (A method is there to communicate). It will not get the Customers, it will return a Query object which can be used to create a Query for getting customers. A better name for the method would be GetQueryableCustomers or maybe GetQueryObjectForCustomers. If we want to use the name GetCustomers, I think the name of the Class which has this member would have the word Query in the name, for example: QueryProvider.GetCustomer. This will make sure the users of the code, know that we are getting a Query nothing else. So when return the IQueryable<T>, we are basically using a Query Provider, which should be used by the Data Access Layer, no other layers.
2) By passing the IQueryable<T> between the layers, we will have a deferred execution. We will "never" know where and when the execution will take place (If we own the code, we will, but not is some other developers want to use our code). For me this is like passing SQL statements from the Data Access Layer up to the Business or Presentation layer for later execution.
By not passing the IQueryable<T> from the Data Access Layer to the Business Logic Layer, we will know when the execution will take place, and when. If we use the Repository Pattern, all execution of Queries should take place inside of the Repository. It sad that the IQueryable<T> is indirect bound to a specific LINQ feature, such as Entity Framework or LINQ to SQL. What I want, is a way to attach a IQueryable<T> to a LINQ feature. In that way I could use it as a replacement of the Specification pattern/Query object pattern, and that would solve a lot of problem and also result in a light weight interface for the Data Access components.
public IEnumerable<Customer> GetCustomersBySpecification(IQueryable<Customer> query)
If this was possible and if we could use Entity Framework or LINQ to SQL as the infrastructure of our Repositories, we could create a Factory to return a IQueryable<T> interface which it not indirectly attached to a specific LINQ feature. In this case we could create our queries in the Business Logic layer, and pass the Query back down to the Data Access Layer and let it attache the Query to a LINQ feature and execute it:
var query = from customer in QueryFactory.GetQuery<Customer>()
where customer.ID = 1234 select customer;
var customers = CustomerRepository.GetCustomerBySpecification(query);
By using this solution we could avoid deferred execution, when and where the execution will take place is under our control.
Before I end this post I want to let you know that the problem is not about returning the IQueryable<T> interface, the problem is how the LINQ features are indirect bound to the IQueryable<T> interface. If it wasn't and we could bind it later, I think we could use it to solve problems in a really wonderful and nice way. What do you think?