LINQ kepada Entitas tidak mengenali metode tersebut

116

Saya mendapatkan kesalahan berikut saat mencoba melakukan kueri LINQ:

LINQ ke Entitas tidak mengenali metode metode 'Boolean IsCharityMatching (System.String, System.String)', dan metode ini tidak dapat diterjemahkan ke dalam ekspresi penyimpanan.

Saya telah membaca banyak pertanyaan sebelumnya di mana orang mendapatkan kesalahan yang sama, dan jika saya memahami ini dengan benar, itu karena LINQ ke Entitas memerlukan seluruh ekspresi kueri LINQ untuk diterjemahkan ke kueri server, dan oleh karena itu Anda tidak dapat memanggil metode luar di dalamnya. Saya belum bisa mengubah skenario saya menjadi sesuatu yang berhasil, dan otak saya mulai mencair, jadi saya berharap seseorang bisa mengarahkan saya ke arah yang benar. Kami menggunakan Entity Framework dan pola spesifikasi (dan saya baru mengenal keduanya).

Berikut kode yang menggunakan spesifikasi tersebut:

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

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

Berikut ekspresi linq:

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

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

Beri tahu saya jika Anda memerlukan informasi lebih lanjut.

Terimakasih banyak,

Annelie

annelie
sumber
periksa jawaban ini
Eranga
Akan memeriksanya juga, terima kasih!
annelie
1
Alangkah baiknya melihat bagaimana Anda menggunakan Find()saat bagaimana Anda menggunakan IsSatisfied()di dalamnya.
Alisson

Jawaban:

124

Seperti yang Anda ketahui, Entity Framework tidak dapat menjalankan kode C # Anda sebagai bagian dari kuerinya. Itu harus dapat mengubah kueri menjadi pernyataan SQL yang sebenarnya. Agar itu berfungsi, Anda harus menyusun ulang ekspresi kueri Anda menjadi ekspresi yang dapat ditangani oleh 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()));
}
StriplingWarrior
sumber
1
jika ragu cari tahu: stackoverflow.com/questions/2352764/…
Chris Hayes
2
Mengembalikan bangunan Expression<Func<T,type>>adalah pendekatan yang sangat bagus untuk ini.
Travis J
Bagaimana Anda akan menggunakan ini dalam ekspresi LINQ? Saya ingin melakukan sesuatu seperti ini sebagai klausa Where yang dapat digunakan kembali tetapi saya berjuang untuk menerapkannya.
Zorgarath
4
EDIT: tidak masalah, itu akan menjadi:context.Where(IsSatisfied())
Zorgarath
Bagian kunci: "Entity Framework tidak dapat benar-benar menjalankan kode C # Anda sebagai bagian dari kuerinya."
Alper
1

Saya mendapat kesalahan yang sama dalam kode ini:

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

inilah tepatnya kesalahan:

System.NotSupportedException: 'LINQ to Entities tidak mengenali metode' Boolean Exists (System.Predicate`1 [conector_gp.Models.almacenes_por_sucursal]) ', dan metode ini tidak dapat diterjemahkan ke dalam ekspresi penyimpanan.'

Saya menyelesaikannya dengan cara ini:

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();

Saya menambahkan .ToList () sebelum tabel saya, ini memisahkan kode Entity dan linq, dan menghindari ekspresi linq saya berikutnya diterjemahkan

CATATAN: solusi ini tidak optimal, karena hindari pemfilteran entitas, dan cukup muat semua tabel ke dalam memori

Ing. Gerardo Sánchez
sumber
1
Sebagian besar waktu ini solusi termudah tetapi untuk tidak memuat semua objek saya biasanya membuat pilihan anonim sebelum .ToList () dengan hanya apa yang saya butuhkan ... xx.Select (x => new {x.Id, x.DateTimeUpdate }). ToList (). Pilih (x => baru {x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString ("dd / MM / yyyy")})
Diógenes
0

Jika ada yang mencari jawaban VB.Net (seperti saya awalnya), ini dia:

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
Mik
sumber
-1

Saya memiliki masalah yang serupa dengan Anda dan dokumentasi LINQ ini membantu saya menemukan fungsi string yang tepat untuk mengatasi batasan tersebut.

Michael Fayad
sumber