I just finished writing an article about Expression Trees for Visual Studio Magazine (aka VBPJ) and there seemed to be some “holes” that I think should be plugged. An expression tree is basically a descriptive way of representing a lambda function. The standard LINQ query operators (e.g Where Group, Join et al) on an IQueryable will cause the language compilers to compile the lambda function as an expression tree. From there the expression basically allows for translation between, such as VB or C# to TSQL.
A problem with this “translation” is that it is not 100%… that is, not all things you write in a lambda can be translated. If you think about TSQL for example you can see there is a very finite limit of what can and what can’t be translated. Unfortunately the way things are you don’t and can’t really get any design time feedback on this. For example, the extension methods in Queryable work for any IQueryable, so without a runtime analysis of the IQueryable.Provider you can’t really ask for what language features it supports.
So…. this got me thinking… What about a couple of design time attributes ? The first would be on your collection/IEnumerable /data source and would specify the provider from which to query the supported features. This might take the form of <QueryProvider(“MyEntityFramework”)> . The “MyEntityFramework” should be the qualified named for the actual IQueryable.Provider .
The next problem is an extension method doesn’t tell us if it is going to use the provider or return the same provider, so we need an attribute on them to do so. e.g <QueryProvider(UsesProvider:= True, ReturnsSameProvider:= True)> . We probably need a third property for this attribute that specifies the Provider it returns if ReturnsSameProvider is false.
Finally, a third attribute for the provider itself to indicate whether it is the design time service provider as well or the fully qualified class name for the design time service provider.
Then, it should be possible to provide a great design time experience for any query provider.