6

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

検索が行われると、 ORで始まるエンティティ、または検索で始まるエンティティを検索するクエリを作成しようとしてtermいます。(これはクエリの一部ですが、sはにのみ一致する必要があるため、問題が発生している場所ではありません。)PlaceOfficialNametermPlaceNameTextAsciiEquivalenttermLanguagePlaceNameCultureInfo.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 => ...他のクエリで再利用できるようにすることです。これが私が試した1つの例ですが、これは機能せず、例外 ""をスローします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()ましたが、常に前述の例外の1つになります。

LINQ to Entities with LinqKit / PredicateBuilderを使用して、この式を別のメソッドに分解することも可能ですか?もしそうなら、どのように?私は何が間違っているのですか?

4

1 に答える 1

7

以下の方法が機能するはずです。

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. LinkKitExpandメソッドを呼び出します。これにより、呼び出された式が展開されます。

于 2012-05-29T20:00:12.200 に答える