2008-10-29 4 views
5

우리는 우리 시스템에서 LINQ를 매우 널리 사용하고 있습니다. 특히 LINQ-to-objects. 따라서 일부 장소에서는 LINQ 쿼리를 사용하여 거대한 표현으로 메모리를 구축하게됩니다. 문제는 표현식에 버그가있을 때입니다. 그래서 우리는 NullReferenceException을 얻었고 스택 트레이스는 우리를 아무 곳에도 이끌지 않습니다 ([Lightweight Function]으로). 예외가 LINQ에 의해 생성 된 동적 메서드 내에서 throw되었습니다..NET 동적 메서드 디버깅

그런 동적 방법을 디버깅하는 쉬운 방법이 있습니까? 아니면 WinDBG 학습에 자신을 희생해야합니까? :-)

+0

Linq to 개체는 일반적으로 System.Linq.Enumerable의 메서드를 참조합니다. 동적 메서드는 포함하지 않지만 익명 메서드가 포함될 수 있습니다. 당신은 정말로 동적 인 방법을 사용하고 있습니까? –

+0

@David - 나는 같은 질문을했다. Orlangur는 AsQueryable을 사용하여 여러 소스에서 동일한 코드를 사용하므로 동적 방법이 필요합니다. –

답변

3

자신 만의 표현식을 작성하고 컴파일하거나 AsQueryable을 사용하는 경우 예; LINQ로 생성 된 메서드는 디버깅 할 때 고질적 인 문제가됩니다.

당신은 실제 방법의 작은 fragements를 사용하여 약간의 고통을 절약 할 수 있습니다

- 스택 추적에 표시됩니다 유용한 적어도 뭔가를 ...

또 다른 고려 사항은 다음과 같습니다 오히려 하나 개의 거대한 표현을하는 것보다, 당신이 할 수있는 경우 데이지 - 체인 (daisy-chain) 일을 좀 더하면 스택 트레이스에서 더 많은 아이디어를 얻을 수있다. 단점은 성능입니다. Where (foo) .Where (bar)는 두 개의 대리자 호출이며 where-as (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; 
      } 
     } 
    } 
} 
+0

불행히도 표현식을 만드는 코드가 다른 LINQ 제공자와 함께 사용되기 때문에 실제 메서드는 우리의 경우 옵션이 아닙니다. IQueryable과 함께 사용해야합니다. –

+0

[Fairs ...] –

+0

글쎄, 내가 만들 수 있다고 생각합니다. 모든 표현식을 재귀 적으로 평가하고 디버깅을위한 내 자신의 LINQ-to-objects 공급자는 반복적으로 모든 식을 평가하고 쿼리 가능한 메서드 호출을 열거 가능한 메서드 호출로 대체합니다. 그게 문제를 해결해야합니다. 그러나 쉬운 일 자체가 아닙니다. –

1

LINQ to Objects를 사용하는 경우 동적 메서드가 생성되는 것을 기대하지 않을 것입니다. 나는 LINQ와 SQL 등 그들을 기대할 수 있습니다. 당신은 당신이 이것을보고있는 예를 줄 수 있을까요?

나는 LINQ에 관해서는 좋은 디버깅 팁이 없다.하지만 MS는 이것을 고통 점으로 알고있다. VS2010 CTP을 시도해 보시고 그게 더 낫다는 것을 제안 해 주시겠습니까? VS 문제를 해결하는 것보다 VS 개선을 위해 더 많은 것을 인정합니다.

+0

LINQ to Objects로 AsQueryable()을 통해 메모리 내 컬렉션 사용하기 –

+0

AsQueryable을 사용하는 이유는 무엇입니까? * 일반적으로 * IEnumerable 은 더 간단하며 간단한 람다를 직접 사용할 수 있습니다. 당신은 여전히 ​​그들을 사용할 수있는 수동으로 빌드 된 람다를 컴파일() 할 수 있습니다 ... –

+0

(아, 맞아요, 내 게시물에 대답) –