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;
}

さらに情報が必要な場合はお知らせください。

どうもありがとう、

アンリー



これもチェックしてくれてありがとう!
Annlie

1
内部でFind()どのように使用するのか、どのように使用しているのかを確認するとよいでしょうIsSatisfied()
Alisson 2017年

回答:


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年

4
編集:気にしないでください、それは次のようになります:context.Where(IsSatisfied())
Zorgarath

重要な部分:「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()を追加しました。これにより、エンティティと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ógenesJan

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.