2008-10-29 17 views
5

Estamos utilizando LINQ de forma muy amplia en nuestro sistema. Particularmente LINQ-to-objects. Entonces, en algunos lugares, terminamos teniendo una consulta LINQ en acumulación de memoria a partir de algunas expresiones enormes. El problema surge cuando hay algún error en las expresiones. Así que obtenemos NullReferenceException y el seguimiento de la pila no nos lleva a ninguna parte (a [Lightweight Function]). La excepción fue lanzada dentro del método dinámico generado por LINQ.Depuración de métodos dinámicos .NET

¿Hay alguna manera fácil de solucionar estos métodos dinámicos? ¿O debo sacrificarme para aprender WinDBG? :-)

+0

Linq a los objetos generalmente se refiere a los métodos de System.Linq.Enumerable. Estos no involucran métodos dinámicos (pero pueden involucrar métodos anónimos). ¿Estás realmente usando métodos dinámicos? –

+0

@David - Pregunté lo mismo; Orlangur está usando AsQueryable para usar el mismo código con múltiples fuentes, por lo que se esperan métodos dinámicos. –

Respuesta

3

Si está construyendo sus propias expresiones y compilándolas, o usando AsQueryable, entonces sí; los métodos generados por LINQ serán un verdadero dolor para depurar.

Usted puede ahorrar algo de dolor mediante el uso de pequeñas fragements de métodos reales - al menos algo útil mostrará en el seguimiento de la pila ...

Otra consideración es: en lugar de tener una gran expresión, si es posible encadena las cosas un poco más, es posible que tengas más idea (del rastro de la pila) de dónde está fallando. La desventaja es el rendimiento: un Where (foo) .Where (bar) es dos invocaciones de delegado, donde-como Where (foo & & bar) puede ser uno.

Una opción podría ser cambiar una versión de depuración de los métodos de extensión; por desgracia, es un poco incómodo porque IQueryable<T> y Queryable están en el mismo espacio de nombres ... esto funciona, aunque ...

salida primero:

>Where: x => ((x % 2) = 0) 
<Where: x => ((x % 2) = 0) 
>Count 
'WindowsFormsApplication2.vshost.exe' (Managed): Loaded 'Anonymously Hosted DynamicMethods Assembly' 
<Count 

Código:

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; 
      } 
     } 
    } 
} 
+0

Desafortunadamente los métodos actuales no son una opción en nuestro caso ya que el código que construye las expresiones también se usa con otros proveedores LINQ así que tiene que funcionar con IQueryable –

+0

Lo suficientemente justo [piensa ...] –

+0

Bueno, creo que puedo crear mi propio proveedor LINQ-to-objects específicamente para la depuración que evaluará todas las expresiones paso a paso de forma recursiva y reemplazará las llamadas a métodos consultables con llamadas de método enumerables. Eso debería resolver el problema. No es una tarea fácil en sí misma sin embargo. –

1

Si está utilizando LINQ to Objects, no esperaría que se crearan métodos dinámicos. Los esperaría con LINQ a SQL, etc. ¿Podría darnos un ejemplo de dónde está viendo esto?

Realmente no tengo ninguna buena sugerencia de depuración cuando se trata de LINQ, pero estoy bastante seguro de que MS sabe de esto como un punto de dolor. ¿Puedo sugerirle que pruebe el VS2010 CTP y vea si eso es mejor? Más para mejorar VS que para resolver su problema inmediato, lo admito.

+0

Por LINQ to Objects me refiero al uso de colecciones en memoria a través de AsQueryable() –

+0

¿Por qué AsQueryable? * generalmente * IEnumerable es más simple, y significa que las lambdas simples pueden usarse directamente. Todavía puedes .Compilar() tus lambdas construidas manualmente para usarlas ... –

+0

(ah, sí, respondiste eso en mi publicación) –

Cuestiones relacionadas