문제

저는 LINQ 표현식을 메서드로 리팩터링하려고 노력해 왔으며 "Internal .NET Framework Data Provider error 1025." 그리고 "The parameter 'xyz' was not bound in the specified LINQ to Entities query expression." 예외.

엔터티 모델의 관련 부분은 다음과 같습니다(EF 4.2/LINQ to Entities 사용).

public class Place : Entity
{
    public string OfficialName { get; protected internal set; }
    public virtual ICollection<PlaceName> { get; protected internal set; }
}

public class PlaceName : Entity
{
    public string Text { get; protected internal set; }
    public string AsciiEquivalent { get; protected internal set; }
    public virtual Language TranslationTo { get; protected internal set; }
}

public class Language : Entity
{
    public string TwoLetterIsoCode { get; protected internal set; }
}

기본적인 관계형 모델은 다음과 같습니다.

Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language

검색이 제공되면 해당 쿼리를 작성하려고 합니다. term, 찾아보세요 Place 그 실체 OfficialName 로 시작합니다 term 또는 PlaceName 누구의 Text 또는 AsciiEquivalent 검색으로 시작됩니다 term. (Language 쿼리의 일부이긴 하지만 문제가 있는 부분은 아닙니다. PlaceNames는 다음에 대해서만 일치해야 합니다. CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName.)

다음 코드 작동합니까:

internal static IQueryable<Place> WithName(this IQueryable<Place> queryable, 
    string term)
{
    var matchesName = OfficialNameMatches(term)
        .Or(NonOfficialNameMatches(term));
    return queryable.AsExpandable().Where(matchesName);
}

private static Expression<Func<Place, bool>> OfficialNameMatches(string term)
{
    return place => place.OfficialName.StartsWith(term);
}

private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
    var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
    return place => place.Names.Any(
        name =>
        name.TranslationToLanguage != null
        &&
        name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
        &&
        (
            name.Text.StartsWith(term)
            ||
            (
                name.AsciiEquivalent != null
                &&
                name.AsciiEquivalent.StartsWith(term)
            )
        )
    );
}

내가 다음에 하려는 일은 NonOfficialNameMatches 추출하는 방법 name => ... 다른 쿼리에서 재사용할 수 있도록 표현식을 별도의 메서드로 변환합니다.다음은 제가 시도한 한 가지 예입니다. 작동하지 않습니다 예외가 발생합니다."The parameter 'place' was not bound in the specified LINQ to Entities query expression.":

private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
    return place => place.Names.AsQueryable().AsExpandable()
        .Any(PlaceNameMatches(term));
}

public static Expression<Func<PlaceName, bool>> PlaceNameMatches(string term)
{
    var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
    return name =>
            name.TranslationToLanguage != null
            &&
            name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
            &&
            (
                name.Text.StartsWith(term)
                ||
                (
                    name.AsciiEquivalent != null
                    &&
                    name.AsciiEquivalent.StartsWith(term)
                )
            );
}

내가 가지고 있지 않을 때 .AsExpandable() 체인 연결 NonOfficialNameMatches, 그러면 "Internal .NET Framework Data Provider error 1025." 예외.

나는 팔로우했다 여기에 다른 조언 여러 가지 호출 조합과 같은 .Expand() 그러나 항상 앞서 언급한 예외 중 하나로 끝납니다.

LinqKit/PredicateBuilder와 함께 LINQ to Entities를 사용하여 이 표현식을 별도의 메서드로 분리하는 것이 가능합니까? 그렇다면 어떻게?내가 도대체 ​​뭘 잘못하고있는 겁니까?

도움이 되었습니까?

해결책

아래 방법이 작동합니다.

private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
    Expression<Func<PlaceName, bool>> placeNameExpr = PlaceNameMatches(term);
    Expression<Func<Place, bool>> placeExpr =
        place => place.Names.Any(name => placeNameExpr.Invoke(name));
    return placeExpr.Expand();
}

편집하다:추가 설명 추가

그만큼 PlaceNameMatches 방법은 작성한 대로 작동합니다.문제는 방법을 사용하는 방법에 있었습니다.표현식의 일부를 제외하려면 위 방법에서 수행한 3단계를 따르세요.

  1. 메소드에 의해 생성된 표현식에 지역 변수를 설정합니다.

  2. 다른 지역 변수를 지역 변수 표현식을 호출하는 새 표현식으로 설정합니다.

  3. LinkKit 호출 Expand 방법:이렇게 하면 호출된 표현식이 확장됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top