Implement IQueryable wrapper to translate result objects

橙三吉。 提交于 2019-11-30 04:53:39
dbarnes

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!