2008-10-29 14 views
5

Używamy LINQ bardzo szeroko w naszym systemie. W szczególności LINQ-to-objects. Tak więc w niektórych miejscach otrzymujemy kwerendę LINQ w pamięci zbudowaną z wielkich wyrażeń. Problem pojawia się, gdy występuje błąd w wyrażeniach. Otrzymujemy więc NullReferenceException, a ślad stosu prowadzi nas nigdzie (do [Funkcja lekka]). Wyjątek został zgłoszony wewnątrz metody dynamicznej generowanej przez LINQ.Debugowanie metod dynamicznych .NET

Czy istnieje prosty sposób debugowania takich dynamicznych metod? Czy muszę poświęcać się na naukę WinDBG? :-)

+0

Linq do obiektów zwykle odnosi się do metod System.Linq.Enumerable. Nie obejmują one metod dynamicznych (ale mogą obejmować metody anonimowe). Czy naprawdę używasz metod dynamicznych? –

+0

@ David - pytałem to samo; Orlangur używa AsQueryable do używania tego samego kodu z wieloma źródłami - więc oczekuje się metod dynamicznych. –

Odpowiedz

3

Jeśli tworzysz własne wyrażenia i kompilujesz je lub używasz AsQueryable, to tak; metody generowane przez LINQ będą królewskim problemem do debugowania.

Można zaoszczędzić trochę bólu za pomocą małych fragements z rzeczywistych metod - przynajmniej coś pożytecznego pokaże w ślad stosu ...

Innym zjawiskiem jest: zamiast jednego ogromną ekspresją, jeśli potrafisz niweluj coś w łańcuchu, aby uzyskać więcej pomysłów (z wykresu stosu), w których nie działa. Minusem jest wydajność - a Gdzie (foo) .W przypadku (bar) jest dwa razy wywoływane przez delegata, gdzie - jako Gdzie (foo & & bar) może być jeden.

Jedną opcją może być zamiana wersji debugowania metod rozszerzeń; niestety jest to trochę niewygodne, ponieważ IQueryable<T> i Queryable są w tej samej przestrzeni nazw ... to działa, chociaż ...

Wyjście pierwsze:

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

Kod:

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

Niestety, w naszym przypadku rzeczywiste metody nie są dostępne, ponieważ kod budujący wyrażenia jest używany również z innymi dostawcami LINQ, więc musi działać z IQueryable –

+0

Wystarczająco fair [myśli ...] –

+0

Cóż, myślę, że mogę stworzyć mój własny dostawca LINQ-do-obiektów specjalnie do debugowania, który oceni rekurencyjnie wszystkie wyrażenia krok po kroku i zastąpi wywoływalne wywołania metodowe z wyliczalnymi wywołaniami metod. To powinno rozwiązać problem. Jednak nie jest to łatwe zadanie. –

1

Jeśli używasz LINQ do Objects, nie spodziewałbym się utworzenia metod dynamicznych. Spodziewałbym się ich z LINQ do SQL itp. Czy mógłbyś podać przykład, w którym to widzisz?

Naprawdę nie mam żadnych dobrych wskazówek do debugowania, jeśli chodzi o LINQ, ale jestem pewien, że MS wie o tym jako o punkcie bólu. Czy mógłbym zaproponować ci wypróbowanie VS2010 CTP i sprawdzić, czy to jest lepsze? Co więcej, ze względu na poprawę VS, niż na rozwiązanie twojego bezpośredniego problemu, trzeba przyznać.

+0

Przez LINQ do obiektów mam na myśli za pomocą kolekcji w pamięci za pośrednictwem AsQueryable() –

+0

Dlaczego więc AsQueryable? * ogólnie * IEnumerable jest prostsze i oznacza, że ​​proste lambdy mogą zostać użyte bezpośrednio. Nadal możesz .Compile() ręcznie zbudować lambdas, aby z nich korzystać ... –

+0

(ah right, odpowiedziałeś na to w moim poście) –

Powiązane problemy