我们在系统中广泛使用LINQ。特别是对对象的LINQ。因此,在某些地方,我们最终会在内存中使用一些大型表达式构建LINQ查询。当表达式中出现错误时,问题就出现了。因此,我们得到了NullReferenceException,而堆栈跟踪却没有任何结果(指向[Lightweight Function])。在LINQ生成的动态方法内部引发了异常。
有什么简单的方法可以调试这种动态方法吗?还是我必须牺牲自己来学习WinDBG?:-)
如果您正在构建自己的表达式并编译它们,或者使用AsQueryable,那么是;LINQ生成的方法将是一个很难调试的问题。
您可以通过使用实际方法的小片段来节省一些痛苦-至少在堆栈跟踪中会显示一些有用的东西。。。
另一个考虑因素是:与其有一个巨大的表达式,如果你能把事情串得更多,你可能会(从堆栈跟踪)更清楚它在哪里失败。缺点是性能——Where(foo)。Where(bar)是两个委托调用,其中as Where(foo&&bar)可以是一个。
一种选择可能是交换扩展方法的调试版本;不幸的是,这有点不方便,因为IQueryable<T>
和Queryable
在同一个命名空间中。。。这是有效的,尽管。。。
输出优先:
>Where: x => ((x % 2) = 0)
<Where: x => ((x % 2) = 0)
>Count
'WindowsFormsApplication2.vshost.exe' (Managed): Loaded 'Anonymously Hosted DynamicMethods Assembly'
<Count
代码:
using System;
using System.Diagnostics;
using System.Linq.Expressions;
namespace Demo
{
using DebugLinq;
static class Program
{
static void Main()
{
var data = System.Linq.Queryable.AsQueryable(new[] { 1, 2, 3, 4, 5 });
data.Where(x => x % 2 == 0).Count();
}
}
}
namespace DebugLinq
{
public static class DebugQueryable
{
public static int Count<T>(this System.Linq.IQueryable<T> source)
{
return Wrap(() => System.Linq.Queryable.Count(source), "Count");
}
public static System.Linq.IQueryable<T> Where<T>(this System.Linq.IQueryable<T> source, Expression<Func<T, bool>> predicate)
{
return Wrap(() => System.Linq.Queryable.Where(source, predicate), "Where: " + predicate);
}
static TResult Wrap<TResult>(Func<TResult> func, string caption)
{
Debug.WriteLine(">" + caption);
try
{
TResult result = func();
Debug.WriteLine("<" + caption);
return result;
}
catch
{
Debug.WriteLine("!" + caption);
throw;
}
}
}
}
如果您使用LINQ to Objects,我不希望看到创建动态方法。我希望他们能使用LINQ到SQL等。你能举一个例子吗?
当谈到LINQ时,我并没有任何好的调试技巧,但我确信MS知道这是一个痛点。我可以建议你试试VS2010 CTP,看看它是否更好吗?无可否认,更多的是为了改进VS,而不是为了解决眼前的问题。
看看最初由Haibo Luo开发并由Roy Osherove 进一步开发的动态方法调试可视化工具