c# - Tracing Linq expression evaluation -


i'm wondering if it's possible write "passthrough" extension method iqueryable write debugstring whenever queryable evaluated, in other words, debug print should side-effect of evaluation.

something like:

var qr = somesource.where(...).orderby(...).trace("somesource evaluated @ {0}", datetime.now) var qr2 = qr.where(...); 

when construct linq query , pass data source object, i'd know when , how object evaluate query. suppose can achieved in other ways, example wrapping ienumerable.getenumerator, i'd generically linq query.

i've done similar, more complex (because manipulates expressions processes them). in order accomplish it, created wrapper class implemented iqueryable , contained reference thing wanted query. made pass interface members through referenced object except provider property, returned reference class created inherited iqueryprovider. iqueryprovider has methods called whenever query constructed or executed. if don't mind being forced query wrapper object(s) instead of original object(s).

you should aware, if you're using linq-to-sql, there's log property on datacontext can use route lots of debug information wherever want.

sample code:

make own iqueryable control queryprovider gets returned.

public class myqueryable(of tabletype)    implements iqueryable(of tabletype)     private innerqueryable iqueryable(of tabletype)    private myprovider myqueryprovider = nothing     public sub new(byval innerqueryable iqueryable(of tabletype))       me.innerqueryable = innerqueryable    end sub     public function getenumerator() system.collections.generic.ienumerator(of tabletype) implements system.collections.generic.ienumerable(of tabletype).getenumerator       return innerqueryable.getenumerator()    end function     public function getenumerator1() system.collections.ienumerator implements system.collections.ienumerable.getenumerator       return innerqueryable.getenumerator()    end function     public readonly property elementtype() system.type implements system.linq.iqueryable.elementtype                return innerqueryable.elementtype       end    end property     public readonly property expression() system.linq.expressions.expression implements system.linq.iqueryable.expression                return innerqueryable.expression       end    end property     public readonly property provider() system.linq.iqueryprovider implements system.linq.iqueryable.provider                if myprovider nothing myprovider = new myqueryprovider(innerqueryable.provider)          return myprovider       end    end property     friend readonly property innertable() system.data.linq.itable                if typeof innerqueryable system.data.linq.itable             return directcast(innerqueryable, system.data.linq.itable)          end if          throw new invalidoperationexception("attempted treat myqueryable table not table")       end    end property end class 

make custom query provider control expression tree gets generated.

public class myqueryprovider    implements iqueryprovider     private innerprovider iqueryprovider     public sub new(byval innerprovider iqueryprovider)       me.innerprovider = innerprovider    end sub    public function createquery(byval expression system.linq.expressions.expression) system.linq.iqueryable implements system.linq.iqueryprovider.createquery       return innerprovider.createquery(expression)    end function     public function createquery1(of telement)(byval expression system.linq.expressions.expression) system.linq.iqueryable(of telement) implements system.linq.iqueryprovider.createquery       dim newquery = innerprovider.createquery(of telement)(convertexpression(expression))       if typeof newquery iorderedqueryable(of telement)          return new myorderedqueryable(of telement)(directcast(newquery, iorderedqueryable(of telement)))       else          return new myqueryable(of telement)(newquery)       end if    end function     public shared function convertexpression(byval expression expression) expression       if typeof expression methodcallexpression          dim mexp = directcast(expression, methodcallexpression)          return expressions.methodcallexpression.call(convertexpression(mexp.object), _             mexp.method, (from row in mexp.arguments select convertexpression(row)).toarray())       elseif typeof expression binaryexpression          dim bexp binaryexpression = directcast(expression, binaryexpression)          dim memberinfo nestedmember = nothing          dim constexp expression = nothing          dim memberonleft boolean          dim doconvert = true          '' [etc... lots of code generate manipulated expression tree       elseif typeof expression lambdaexpression          dim lexp = directcast(expression, lambdaexpression)          return lambdaexpression.lambda( _             convertexpression(lexp.body), (from row in lexp.parameters select _             directcast(convertexpression(row), parameterexpression)).toarray())       elseif typeof expression conditionalexpression          dim cexp = directcast(expression, conditionalexpression)          return conditionalexpression.condition(convertexpression(cexp.test), _                                                 convertexpression(cexp.iftrue), _                                                 convertexpression(cexp.iffalse))       elseif typeof expression invocationexpression          dim iexp = directcast(expression, invocationexpression)          return invocationexpression.invoke( _             convertexpression(iexp.expression), (from row in iexp.arguments _             select convertexpression(row)).toarray())       elseif typeof expression memberexpression          '' [etc... lots of code generate manipulated expression tree       elseif typeof expression unaryexpression          '' [etc... lots of code generate manipulated expression tree       else          return expression       end if    end function     public function execute(byval expression system.linq.expressions.expression) object implements system.linq.iqueryprovider.execute       return innerprovider.execute(expression)    end function     public function execute1(of tresult)(byval expression system.linq.expressions.expression) tresult implements system.linq.iqueryprovider.execute       return innerprovider.execute(of tresult)(convertexpression(expression))    end function end class 

then extend derived datacontext providing wrapped queryables:

partial public class mydatacontext   private myqueries dictionary(of system.type, object) = new dictionary(of system.type, object)   public readonly property my_accountcategories() myqueryable(of accountcategory)              dim result object = nothing         if (me.myqueries.trygetvalue(gettype(accountcategory), result) = false)            result = new myqueryable(of accountcategory)(me.accountcategories)            me.myqueries(gettype(accountcategory)) = result         end if         return ctype(result,myqueryable(of accountcategory))      end   end property   public readonly property my_accountsegmentations() myqueryable(of accountsegmentation)              dim result object = nothing         if (me.myqueries.trygetvalue(gettype(accountsegmentation), result) = false)            result = new myqueryable(of accountsegmentation)(me.accountsegmentations)            me.myqueries(gettype(accountsegmentation)) = result         end if         return ctype(result,myqueryable(of accountsegmentation))      end   end property end class 

Comments

Popular posts from this blog

linux - Mailx and Gmail nss config dir -

c# - Is it possible to remove an existing registration from Autofac container builder? -

php - Mysql PK and FK char(36) vs int(10) -