我在这里阅读这篇文章是在
micro ORM上使用的.
作者展示了这个堆栈跟踪:
System.Reflection.Emit.DynamicMethod.CreateDelegate System.Data.Linq.sqlClient.ObjectReaderCompiler.Compile System.Data.Linq.sqlClient.sqlProvider.GetReaderFactory System.Data.Linq.sqlClient.sqlProvider.System.Data.Linq.Provider.IProvider.Compile System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.ExecuteKeyQuery System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.Execute System.Linq.Enumerable.SingleOrDefault System.Data.Linq.EntityRef`1.get_Entity
然后说:
In the trace above you can see that ‘EntityRef’ is baking a method,which is not a problem,unless it is happening 100s of times a second.
解决方法
当你做类似的事情:
int[] items = whatever; IEnumerable<int> query = from item in items where item % 2 == 0 select item;
然后编译器将其转换为:
static bool Predicate(int item) { return item % 2 == 0; } ... IEnumerable<int> query = Enumerable.Where<int>(items,new Func<int,bool> (Predicate));
也就是说,编译器为该方法生成IL.在运行时构建查询对象时,Where返回的对象保留在谓词的委托上,并在必要时执行谓词.
但是,如果您愿意,可以在运行时为委托构建IL.你所做的是将谓词的主体持久化为表达式树.在运行时,表达式树可以动态地将自身编译成全新的IL;基本上我们启动了一个非常简化的编译器,它知道如何为表达式树生成IL.这样,您可以在运行时更改谓词的详细信息并重新编译谓词,而无需重新编译整个程序.