Update 2013-08-22:
After having a look at the \'Building an IQueryable provider series\' (thanks for the link!) I got a bit further. I updated the c
Alright here is my best to answer this
Why does the IQueryable have a Provider which in turn returns an IQueryable again? Doesn't this call for endless recursion? You want to return an IQueryable for this instance
SomeEnumerable.Where(x=>x.Field == something).Select(x=>x.SomeOtherField)
Think JQuery if you are familiar with chaining
Why is it not enough to implement IEnumerator? Why does FirstOrDefault for instance not use the enumerator to get the element? When I debugged the application GetEnumerator() was not called by FirstOrDefault() on my queryable.
Since IQueryable has 2 special properties query provider and query expression:
What is the difference between IQueryable<T> and IEnumerable<T>?
Since the enumerator is not used in every case, where is the correct point to call the translation function? The Execute-methods of the QueryProvider seemed to be the right place. But do I still need the translation call in the Enumerator for some cases?
Execute is the correct place, you will have to parse the expression tree because the provider has no idea what to do when you execute.
I have also added this link that helped me enormously when I implemented my own query provider http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
What you might be able to get away with is using the same way the author in this post takes the dbReader and converts it to actual objects but instead of the reader take your DBEntity and convert it to your BusinessEntity, but I'm not sure if this is possible. Because everytime you add a linq clause(Select,Where...) it creates a new query of that return type, so if you had an entity of DBEntity "entities" and you did entities.Select(x=>x.someField) and some field is say of type int it's now IQueryable, now your model doesn't work because its expecting int and it's getting DBEntitity
By now I found out why I received an exception every time the query has been enumerated: The IQueryable infrastructure of the Entity Framework is implemented very differently from the pattern described in Building an IQueryable provider series, pt. 1.
The blog post suggests to implement GetEnumerator()
by calling Execute()
on the provider.
In contrast, in the EF infrastructure, ObjectQueryProvider's Execute()
method only accepts expressions which return a single result object -- but not an enumerable collection of result objects (this is even documented in the source code). Accordingly, ObjectQuery's GetEnumerator()
method does not call Execute()
but another method getting the result right from the database.
Thus, any translating IQueryable implementation which uses an underlying database query to get the objects must use the same pattern -- the translating GetEnumerator()
method just calls GetEnumerator()
on the underlying database query and injects this into a new TranslatingEnumerator
.