2008-10-29 12 views
5

Nous utilisons LINQ très largement dans notre système. Particulièrement LINQ-to-objects. Donc, dans certains endroits, nous finissons par avoir une requête LINQ en mémoire construite à partir de grandes expressions. Le problème vient quand il y a un bug dans les expressions. Nous obtenons donc NullReferenceException et la trace de la pile ne nous mène nulle part (à [Lightweight Function]). L'exception a été lancée à l'intérieur de la méthode dynamique générée par LINQ.Débogage des méthodes dynamiques .NET

Existe-t-il un moyen facile de déboguer de telles méthodes dynamiques? Ou dois-je me sacrifier pour apprendre WinDBG? :-)

+0

Linq aux objets fait généralement référence aux méthodes de System.Linq.Enumerable. Ceux-ci n'impliquent pas de méthodes dynamiques (mais peuvent impliquer des méthodes anonymes). Utilisez-vous vraiment des méthodes dynamiques? –

+0

@David - J'ai demandé la même chose; Orlangur utilise AsQueryable pour utiliser le même code avec plusieurs sources - donc des méthodes dynamiques sont attendues. –

Répondre

3

Si vous créez vos propres expressions et les compilez, ou si vous utilisez AsQueryable, alors oui; les méthodes générées par LINQ seront une douleur royale à déboguer.

Vous pouvez économiser de la douleur en utilisant de petites Fragements de réelles méthodes - au moins quelque chose d'utile montrera dans la trace de la pile ...

Une autre considération est: plutôt que d'avoir une expression énorme, si vous le pouvez daisy-chain les choses un peu plus vous pourriez avoir plus d'idée (de la trace de la pile) où il échoue. L'inconvénient est la performance - un où (foo) .Where (barre) est deux appels de délégué, où-comme Où (foo & & bar) peut être un.

Une option pourrait être d'échanger une version de débogage des méthodes d'extension; malheureusement, il est un peu gênant parce IQueryable<T> et Queryable sont dans le même espace ... cela fonctionne, mais ...

sortie première:

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

code:

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

Malheureusement les méthodes actuelles ne sont pas une option dans notre cas puisque le code qui construit les expressions est aussi utilisé avec d'autres fournisseurs LINQ donc il doit fonctionner avec IQueryable –

+0

Assez juste [pense ...] –

+0

Eh bien, je suppose que je peux créer mon propre fournisseur LINQ-to-objects spécifiquement pour le débogage qui évaluera toutes les expressions étape par étape de manière récursive et remplacera les appels de méthodes interrogeables par des appels de méthode énumérables. Cela devrait résoudre le problème. Ce n'est pas une tâche facile en soi. –

1

Si vous utilisez LINQ to Objects, je ne m'attendrais pas à voir des méthodes dynamiques créées. Je les attendrais avec LINQ to SQL, etc. Pourriez-vous donner un exemple où vous voyez ceci?

Je n'ai pas vraiment de bonnes astuces de débogage quand il s'agit de LINQ, mais je suis à peu près sûr que MS en est conscient. Pourrais-je vous suggérer d'essayer le VS2010 CTP et voir si c'est mieux? Plus pour améliorer VS que pour résoudre votre problème immédiat, certes.

+0

Par LINQ to Objects, je veux dire utiliser des collections en mémoire via AsQueryable() –

+0

Alors pourquoi AsQueryable? * généralement * IEnumerable est plus simple, et cela signifie que les simples lambdas peuvent être utilisés directement. Vous pouvez toujours .Compiler() votre lambdas manuellement construit pour les utiliser ... –

+0

(ah droite, vous avez répondu que sur mon poste) –