LINQ to Entities에서 메서드를 인식하지 못합니다.


116

linq 쿼리를 시도 할 때 다음 오류가 발생합니다.

LINQ to Entities는 'Boolean IsCharityMatching (System.String, System.String)'메서드를 인식하지 않으며이 메서드는 저장소 식으로 변환 할 수 없습니다.

나는 사람들이 동일한 오류를 얻는 이전 질문을 많이 읽었으며 이것을 올바르게 이해하면 LINQ to Entities에서 전체 linq 쿼리 식을 서버 쿼리로 변환해야하므로 외부 메서드를 호출 할 수 없기 때문입니다. 그것에. 내 시나리오를 아직 작동하는 것으로 전환 할 수 없었고 뇌가 녹기 시작했기 때문에 누군가가 나를 올바른 방향으로 안내 할 수 있기를 바랐습니다. 우리는 Entity Framework와 사양 패턴을 사용하고 있습니다.

사양을 사용하는 코드는 다음과 같습니다.

ISpecification<Charity> specification = new CharitySearchSpecification(charityTitle, charityReference);

charities = charitiesRepository.Find(specification).OrderBy(p => p.RegisteredName).ToList();

다음은 linq 표현식입니다.

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    return p => p.IsCharityMatching(this.charityName, this.charityReference);
}

IsCharityMatching 메서드는 다음과 같습니다.

public bool IsCharityMatching(string name, string referenceNumber)
{
    bool exists = true;

    if (!String.IsNullOrEmpty(name))
    {
        if (!this.registeredName.ToLower().Contains(name.ToLower()) &&
            !this.alias.ToLower().Contains(name.ToLower()) &&
           !this.charityId.ToLower().Contains(name.ToLower()))
        {
            exists = false;
        }
    }

    if (!String.IsNullOrEmpty(referenceNumber))
    {
        if (!this.charityReference.ToLower().Contains(referenceNumber.ToLower()))
        {
            exists = false;
        }
    }

    return exists;
}

추가 정보가 필요하면 알려주세요.

감사합니다.

Annelie



이것도 확인하겠습니다, 감사합니다!
annelie

1
내부에서 Find()어떻게 사용 하는지 언제 사용하는지 보는 것이 좋을 IsSatisfied()것입니다.
Alisson

답변:


124

아시다시피 Entity Framework는 실제로 쿼리의 일부로 C # 코드를 실행할 수 없습니다. 쿼리를 실제 SQL 문으로 변환 할 수 있어야합니다. 이 작업을 수행하려면 쿼리 식을 Entity Framework가 처리 할 수있는 식으로 재구성해야합니다.

public System.Linq.Expressions.Expression<Func<Charity, bool>> IsSatisfied()
{
    string name = this.charityName;
    string referenceNumber = this.referenceNumber;
    return p => 
        (string.IsNullOrEmpty(name) || 
            p.registeredName.ToLower().Contains(name.ToLower()) ||
            p.alias.ToLower().Contains(name.ToLower()) ||
            p.charityId.ToLower().Contains(name.ToLower())) &&
        (string.IsNullOrEmpty(referenceNumber) ||
            p.charityReference.ToLower().Contains(referenceNumber.ToLower()));
}

1
때 의심 그것을 밖으로 검색 : stackoverflow.com/questions/2352764/...
크리스 헤이즈

2
생성 된 것을 반환하는 Expression<Func<T,type>>것은 이것에 대한 아주 좋은 접근 방식입니다.
Travis J

LINQ 표현식에서 이것을 어떻게 사용 하시겠습니까? 재사용 가능한 Where 절로 이와 같은 작업을 수행하고 싶지만 구현하는 데 어려움을 겪고 있습니다.
Zorgarath 2017-10-27

4
편집 : 신경 context.Where(IsSatisfied())
쓰지 마세요

핵심 부분 : "Entity Framework는 실제로 쿼리의 일부로 C # 코드를 실행할 수 없습니다."
Alper

1

이 코드에서 동일한 오류가 발생했습니다.

 var articulos_en_almacen = xx.IV00102.Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

이것은 정확히 오류였습니다.

System.NotSupportedException : 'LINQ to Entities는'Boolean Exists (System.Predicate`1 [conector_gp.Models.almacenes_por_sucursal]) '메서드를 인식하지 않으며이 메서드는 저장소 식으로 변환 할 수 없습니다.'

이 방법으로 해결했습니다.

var articulos_en_almacen = xx.IV00102.ToList().Where(iv => alm_x_suc.Exists(axs => axs.almacen == iv.LOCNCODE.Trim())).Select(iv => iv.ITEMNMBR.Trim()).ToList();

테이블 앞에 .ToList () 를 추가 하여 Entity와 linq 코드를 분리하고 다음 linq 표현식이 번역되지 않도록합니다.

참고 : 엔티티 필터링을 피하고 모든 테이블을 메모리에로드하기 때문에이 솔루션은 최적이 아닙니다.


1
대부분의 경우 이것은 가장 쉬운 해결책이지만 모든 객체를로드하지 않는 경우 일반적으로 필요한 것만으로 .ToList () 전에 익명 선택을합니다. xx.Select (x => new {x.Id, x.DateTimeUpdate }). ToList (). Select (x => new {x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString ( "dd / MM / yyyy")})
Diógenes

0

누군가가 VB.Net 답변을 찾고 있다면 (처음처럼) 여기에 있습니다.

Public Function IsSatisfied() As Expression(Of Func(Of Charity, String, String, Boolean))

Return Function(charity, name, referenceNumber) (String.IsNullOrWhiteSpace(name) Or
                                                         charity.registeredName.ToLower().Contains(name.ToLower()) Or
                                                         charity.alias.ToLower().Contains(name.ToLower()) Or
                                                         charity.charityId.ToLower().Contains(name.ToLower())) And
                                                    (String.IsNullOrEmpty(referenceNumber) Or
                                                     charity.charityReference.ToLower().Contains(referenceNumber.ToLower()))
End Function

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