質問

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を使用したエンティティを使用):

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は、PlaceNameのみに照合する必要があるため、CultureInfo.CurrentUICulture.TwoLetterIsoLanguageNameはQueryの一部です。)

次のコードが働く

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メソッドをRefactorにして、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()のいくつかの組み合わせなど、常に1つになっています。前述の例外の。

この式をLINQKIT / PRESICATEBUILDERを使用してLINQを使用して別の方法にすることもできますか?では、どうやって?私は何を間違っていますか?

役に立ちましたか?

解決

以下の方法は機能するべきです:

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

  4. に展開されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top