2008-12-04 1 views
2

는 다음 코드 줄을 고려하십시오. 캡쳐 된 변수를 표현식에 사용하면 다음 오류가 발생합니다.주면서

No mapping exists from object type ReportBuilder.Reporter+<>c__DisplayClass0 to a known managed provider native type.

왜? 어떻게 해결할 수 있습니까?

+0

아니겠습니까? 나는 미래를 염두에두고 그것을 지킬 것입니다 ... –

답변

9

기술적으로 정확한 수정 방법은 람다의 표현 트리를 받아 들여 i 참조를 평가하는 프레임 워크입니다. 즉, 특정 프레임 워크에 대한 LINQ 프레임 워크 제한 사항입니다. 현재 시도하고있는 것은 i을 데이터베이스에서 제공자 (제공자)가 알고있는 어떤 유형의 구성원 액세스로 해석하는 것입니다. 람다 변수 캡처가 작동하는 방식 때문에 로컬 변수 은 실제로 공급자가 인식하지 못하는 재미있는 이름을 가진 숨겨진 클래스의 필드입니다.

그래서 프레임 워크 문제입니다.

ParameterExpression x = Expression.Parameter(typeof(RptCriteriaHint), "x"); 
var query = repo.Find(
    Expression.Lambda<Func<RptCriteriaHint,bool>>(
     Expression.Equal(
      Expression.MakeMemberAccess(
       x, 
       typeof(RptCriteriaHint).GetProperty("CriteriaTypeID")), 
      Expression.Constant(i)), 
     x)).ToList(); 

을 ...하지만 그건 그냥 마조히즘 : 당신이 정말 그럭저럭해야하는 경우

, 당신은 다음과 같이 수동으로 표현식을 구성 할 수있다.

이 항목에 대한 귀하의 의견은 더 이상의 설명을 요구합니다.

람다는 올바른 서명이있는 델리게이트이거나 올바른 서명이 Expression<TDelegate> 인 두 가지 유형 중 하나로 변환 할 수 있습니다. LINQ와 외부 데이터베이스 (모든 종류의 메모리 내 쿼리와 반대)는 두 번째 종류의 변환을 사용하여 작동합니다.

컴파일러는 약으로, 말하기, 식 트리에 람다 표현식을 변환합니다

  1. 구문 트리를 컴파일러에 의해 구문 분석 -이 모든 코드를 발생합니다.
  2. 변수 캡처를 고려한 후 구문 트리가 다시 작성됩니다. 변수를 캡처하는 것은 일반적인 델리게이트 또는 람다와 같습니다. 따라서 디스플레이 클래스가 생성되고 캡쳐 된 로컬 객체로 옮겨집니다 (이것은 C# 2.0 익명 대리자의 변수 캡처와 동일한 동작입니다).
  3. 새로운 구문 트리가 Expression 클래스에 대한 일련의 호출로 변환되므로 런타임에 구문 분석 된 텍스트를 충실하게 나타내는 개체 트리가 만들어집니다.

외부 데이터 원본에 대한 LINQ는이 표현 트리를 가져 와서 해당 의미 내용에 대해 해석하고 트리 안의 기호식을 해당 컨텍스트와 관련된 것들 (예 : DB의 열)을 참조하거나, 변환 할 즉시 값. 일반적으로 System.Reflection은이 변환을 안내하는 프레임 워크 별 특성을 찾는 데 사용됩니다.

그러나 SubSonic이 도메인 관련 통신을 찾을 수없는 기호 참조를 제대로 처리하지 못하는 것 같습니다. 상징적 인 참고 문헌을 평가하기보다는 펀칭하는 것입니다. 따라서, 그것은 음속 문제입니다.

+0

프레임 워크는 SubSonic 3.0입니다. 그러나 비교 식을 .Find 메서드에 전달하기 전에 평가하면 안됩니까?보는 방법, 비교식이 정규 C# 코드 인 방법? – AngryHacker

+0

아니요, 비교 표현식은 전달되기 전에 평가되지 않습니다 *. –

+0

감사합니다. SubSonic 저자를 방문하여 캡처 된 변수를 처리하지 않는 이유를 확인하겠습니다. – AngryHacker

관련 문제