web-dev-qa-db-fra.com

Comment déboguer une instruction LINQ

J'ai une déclaration Linq to objects

 var confirm = from l in lines.Lines 
 where (l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber) 
 select l;

L'objet de confirmation renvoie un "objet nul ou pas une référence" à l'adresse System.Linq.Enumerable.WhereListIterator`1.MoveNext ()

Si le résultat de la requête était vide, il retournerait simplement un énumérateur vide. Je sais pertinemment qu'il n'y a aucun objet nul dans la déclaration. Est-il possible de parcourir l'instruction LINQ pour voir où elle tombe?

EDIT Quand j'ai dit je sais pertinemment qu'il n'y a pas d'objets nuls il se trouve que je mentais: [ mais la question demeure, même si je suppose que la réponse sera "vous ne pouvez pas vraiment"

LINQPad est une bonne idée, je l'ai utilisé pour apprendre moi-même LINQ, mais je peux recommencer à le regarder comme un outil de style de débogage/slash et de gravure

41
johnc

Je ne sais pas s'il est possible de déboguer depuis VS, mais je trouve LINQPad très utile. Il vous permettra de vider les résultats de chaque partie de la requête LINQ.

29
OwenP

Oui, il est en effet possible de suspendre l'exécution à mi-chemin d'une requête linq.

Convertissez votre linq en style de requête à l'aide d'expressions lambda et insérez une instruction Select qui se retourne quelque part après le point du linq que vous souhaitez déboguer. Un exemple de code le rendra plus clair -

        var query = dataset.Tables[0].AsEnumerable()
            .Where (i=> i.Field<string>("Project").Contains("070932.01"))
 //         .Select(i =>
 //         {return i;}
 //           )
            .Select (i=>i.Field<string>("City"));

Décommentez ensuite les lignes commentées. Assurez-vous que le {return i;} est sur sa propre ligne et insérez-y un point de débogage. Vous pouvez placer cette sélection à tout moment dans votre requête linq longue et compliquée.

31
The amazing Pete

Vous devriez pouvoir définir un point d'arrêt sur l'expression dans la clause where de votre instruction LINQ.

Dans cet exemple, placez le curseur n'importe où dans la section de code suivante:

(l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber)

Puis appuyez F9 ou utilisez le menu ou le menu contextuel pour ajouter le point d'arrêt.

Lorsqu'il est correctement défini, seul le code ci-dessus doit avoir la mise en forme du point d'arrêt dans l'éditeur plutôt que la totalité de l'instruction LINQ. Vous pouvez également regarder dans la fenêtre des points d'arrêt pour voir.

Si vous l'avez défini correctement, vous vous arrêterez à chaque fois à la fonction qui implémente la partie ci-dessus de la requête.

18
Steve Steiner

J'ai écrit un article complet sur cette question publiée sur Simple-Talk.com ( LINQ Secrets Revealed: Chaining and Debugging ) en 2010:

Je parle de LINQPad (comme mentionné précédemment par OwenP) comme un excellent outil external pour Visual Studio. Portez une attention particulière à son extraordinaire méthode Dump (). Vous pouvez injecter cela à un ou plusieurs points d'une chaîne LINQ pour voir vos données visualisées d'une manière incroyablement propre et claire. Bien que très utile, LINQPad est externe à Visual Studio. Je présente donc également plusieurs techniques disponibles pour une utilisation à l'intérieur Visual Studio car parfois il n'est tout simplement pas pratique de migrer un morceau de code vers LINQPad:

(1) Injectez des appels à la méthode d'extension Dump () que je présente dans mon article pour autoriser la journalisation. J'ai commencé avec la méthode Watch () de Bart De Smet dans son article informatif LINQ to Objects - Debugging et j'ai ajouté un étiquetage et une colorisation pour améliorer la visualisation, bien que cela reste pâle par rapport à la sortie Dump de LINQPad.

(2) Apportez la visualisation de LINQPad directement dans Visual Studio avec le complément LINQPad Visualizer de Robert Ivanc. Je ne sais pas si c'était à cause de mes remarques :-), mais les quelques inconvénients présents lorsque j'écrivais mon article ont maintenant tous été admirablement traités dans la dernière version. Il prend entièrement en charge VS2010 et vous permet d'examiner tout objet que vous aimez lors du débogage.

(3) Intégrez des instructions nop au milieu de votre chaîne LINQ afin de pouvoir définir des points d'arrêt, comme décrit précédemment par Amazing Pete.

Mise à jour 2016.12.01

Et je viens d'écrire la suite de l'article ci-dessus, intitulée simplement LINQ Debugging and Visualization , qui révèle que la véritable capacité de débogage LINQ est enfin arrivée dans Visual Studio 2015 avec la nouvelle fonctionnalité sur le point d'être publiée dans OzCode. @ La réponse de Dror à cette question en donne un tout petit aperçu, mais je vous encourage à lire mon nouvel article pour un "mode d'emploi" détaillé. (Et je fais pas travaille pour OzCode. :-)

15
Michael Sorens

[Avertissement: je travaille chez OzCode]

Le problème avec LINQ est qu'il est difficile, voire impossible, de déboguer - même lorsqu'il s'agit de requêtes simples, un développeur est obligé de refactoriser sa requête en un tas de boucles foreach ou d'utiliser la journalisation. Le débogage LINQ est pris en charge dans une version bientôt disponible d'OzCode ( actuellement disponible en tant qu'aperçu d'accès anticipé ) et il aide les développeurs à explorer également leur code LINQ et à identifier les exceptions difficiles à détecter. requêtes internes

Voici à quoi ressemblerait votre requête dans OzCode: Debugging LINQ exception

7
Dror Helper

Il est possible de pénétrer dans l'expression LINQ sans définir de points d'arrêt temporaires. Vous devez entrer dans la fonction qui évalue l'expression LINQ, par exemple:

var confirm = from l in lines.Lines 
              where (l.LineNumber == startline.LineNumber)
                    || (l.LineNumber == endline.LineNumber) 
              select l;

 confirm.ToArray(); // Press F11 ("Step into") when you reach this statement

 foreach(var o in q) // Press F11 when "in" keyword is highlighted as "next statement"
    // ...
6
user1414213562

Vérifiez la trace de la pile d'exceptions et voyez le dernier bit de votre code exécuté.

3

D'après l'apparence de l'erreur, je vous suggère de jeter un œil à line.Lines et de vous assurer que son énumérateur est correctement implémenté. Je pense que cela retourne une valeur nulle alors qu'il ne devrait pas.

Oh et assurez-vous simplement que les objets line et line.Lines ne sont pas nuls ou ne renvoient pas non plus.

3
ljs

Bien que ce ne soit pas un moyen de débogage, je suggère d'utiliser ce qui suit:

using (var db = new AppContext())
        {
            db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
            // Rest of code
        }

Vous pouvez ensuite vérifier la fenêtre de sortie lors du débogage pour voir le SQL généré à partir de votre requête LINQ.

0
Sha