"문 본문이있는 람다 식은 식 트리로 변환 할 수 없습니다"


181

EntityFramework 사용시 A lambda expression with a statement body cannot be converted to an expression tree다음 코드를 컴파일하려고 할 때 " " 오류가 발생 합니다.

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();

오류가 무엇을 의미하는지, 무엇보다도 오류를 해결하는 방법을 모르겠습니다. 어떤 도움?


6
이 같은 목록으로 변환하십시오. objects.List (). Select (...
nelson eldoro

답변:


114

objectsLinq에 - 투 - SQL 데이터베이스 컨텍스트는? 이 경우 => 연산자 오른쪽에 간단한 표현식 만 사용할 수 있습니다. 그 이유는 이러한 표현식이 실행되지 않지만 데이터베이스에 대해 실행되도록 SQL로 변환되기 때문입니다. 이 시도

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();

102

IEnumerable 콜렉션에 대해 람바 표현식에서 명령문 본문을 사용할 수 있습니다 . 이거 한번 해봐:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();


주의 사항 : 이 방법을 사용할 때는 신중하게 생각하십시오 . 이 방법을 사용하면 모든 쿼리 결과가 메모리에 저장되며 나머지 코드에는 원하지 않는 부작용이 발생할 수 있습니다.


4
+1 나는 이것을 좋아한다! AsEnumerable()마스크를 추가하면 문제가 해결됩니다!
Joel

5
이것은 실제 해결책이며, 어떤 경우에는 허용 된 대답을 적용하기가 어렵습니다
Ferran Salguero

15
아니 이것은 실제 답변이 아닙니다. 클라이언트 측에서 쿼리가 실행되도록합니다. 자세한 내용은이 질문을 참조하십시오. stackoverflow.com/questions/33375998/…
Luke Vo

1
@DatVM 그것은 당신이 무엇을 할 것인지에 달려 있습니다. 이것은 항상 올바른 선택 일 수는 없으며 물론 항상 잘못된 선택 일 수는 없습니다.
Amir Oveisi

3
동의하지만 OP는 그가 EntityFramework를 사용하고 있다고 말했습니다. 대부분의 경우 EF로 작업 할 때 데이터베이스 측에서 최대한 많은 작업을 수행하려고합니다. 답변에 사례를 적어두면 좋을 것입니다.
Luke Vo

39

즉, 람다 식을 표현식 트리로 변환해야하는 위치 (예 : linq2sql을 사용하는 경우)에서 "statement body"(예 : 중괄호를 사용하는 람다 식)와 함께 람다 식을 사용할 수 없습니다. .


37
당신은 ... 오류를 약간 수정했습니다.
@Tim

2
@vbullinger 당신은 어느 정도 옳았지만, 더 일반적인 의미 (linq-to-sql의 맥락 밖)에서 이것은 더 직접적인 대답입니다. 그것은 AutoMapper 오류로 저를 도움
mlhDev

1
vbullinger : 그래도 도움이되었습니다.
Paul

7

수행중인 작업 (Linq2Objects, Linq2Entities, Linq2Sql?)에 대해 더 많이 알지 못하면 작동해야합니다.

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();

11
그러면 쿼리 가능 항목이 평가됩니다.
smartcaveman

그러나이 상황에서는 어쨌든 ToArray ()를 호출하기 때문에 괜찮습니다.
smartcaveman

2
"o"가 얼마나 큰지 누가 아는가? 우리가 원하는 것은 2
개일

1
이 기술을 사용할 때, 나는 전화하기 전에 익명의 유형으로 사용할 필드를 선택하고 싶습니다.AsEnumerable()
Blake Mitchell

4

이 선택 과부하를 사용하십시오.

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();

이것은 저에게 효과적이지만 Entity Framework와 함께 사용하면 AsEnumerable ()과 같이 dbcontext가 모든 행을 메모리에 먼저로드하지 못하게합니까?
의회

2
@parliament : 메모리에 모든 행을로드하지 못하게하려면을 사용해야합니다 Expression<Func<Obj,Obj>>.
Mohsen

4

LINQ to SQL 리턴 오브젝트가 IQueryable인터페이스 를 구현하고있었습니다 . 따라서 Select메소드 술어 매개 변수의 경우 본문없이 단일 람다 표현식 만 제공해야합니다.

LINQ for SQL 코드는 SQL Server 또는 다른 서버와 같은 원격 쪽이 아니라 프로그램 내부에서 실행되지 않기 때문입니다. 이 지연로드 실행 유형은 예상 대리자가 아래와 같이 Expression 유형 클래스에 래핑되는 IQueryable을 구현하여 달성되었습니다.

Expression<Func<TParam,TResult>>

표현식 트리는 본문이있는 람다 식을 지원하지 않으며 단일 행 람다 식만 지원합니다. var id = cols.Select( col => col.id );

따라서 다음 코드를 시도하면 작동하지 않습니다.

Expression<Func<int,int>> function = x => {
    return x * 2;
}

다음은 예상대로 작동합니다.

Expression<Func<int,int>> function = x => x * 2;

2

이는를 TDelegate포함하는 유형의 Lambda 표현식을 ([parameters]) => { some code };로 변환 할 수 없음을 의미합니다 Expression<TDelegate>. 규칙입니다.

쿼리를 단순화하십시오. 제공 한 것은 다음과 같이 다시 작성 될 수 있으며 컴파일됩니다.

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();

1

인가 Arr의 기본 유형 Obj? Obj 클래스가 존재합니까? Arr이 기본 유형의 Obj 인 경우에만 코드가 작동합니다. 대신 이것을 시도 할 수 있습니다 :

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();

1

귀하의 특정 경우, 본문은 변수를 만들고, IEnumerable모든 작업이 클라이언트 측에서 처리되도록 전환하기위한 것이므로 다음 해결책을 제안합니다.

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

편집 : C # 코딩 규칙 이름 바꾸기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.