LINQ to Entities yöntemi tanımıyor


116

Bir linq sorgusu yapmaya çalışırken aşağıdaki hatayı alıyorum:

LINQ to Entities, 'Boolean IsCharityMatching (System.String, System.String)' yöntemini tanımıyor ve bu yöntem bir mağaza ifadesine çevrilemez.

İnsanların aynı hatayı aldığı birçok önceki soru okudum ve bunu doğru anlarsam, bunun nedeni LINQ to Entities'in tüm linq sorgu ifadesinin bir sunucu sorgusuna çevrilmesini gerektirmesi ve bu nedenle bir dış yöntemi çağıramamanızdır. içinde. Senaryomu henüz işe yarayan bir şeye dönüştüremedim ve beynim erimeye başladı, bu yüzden birinin beni doğru yöne yönlendirmesini umuyordum. Entity Framework ve belirtim kalıbını kullanıyoruz (ve her ikisinde de yeniyim).

Spesifikasyonu kullanan kod şu şekildedir:

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

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

İşte linq ifadesi:

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

İşte IsCharityMatching yöntemi:

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

Daha fazla bilgiye ihtiyacınız olursa bana bildirin.

Çok teşekkürler,

Annelie



Bunu da kontrol edeceğim, teşekkürler!
annelie

1
İçini Find()nasıl kullandığınızı , nasıl kullandığınızı görmek güzel olurdu IsSatisfied().
Alisson

Yanıtlar:


124

Anladığınız gibi, Entity Framework aslında C # kodunuzu sorgusunun bir parçası olarak çalıştıramaz. Sorguyu gerçek bir SQL deyimine dönüştürebilmelidir. Bunun çalışması için, sorgu ifadenizi Entity Framework'ün işleyebileceği bir ifade olarak yeniden yapılandırmanız gerekir.

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
şüphe duyduğunuzda arayın: stackoverflow.com/questions/2352764/…
Chris Hayes

2
Bir inşaa geri dönmek Expression<Func<T,type>>, buna çok güzel bir yaklaşımdır.
Travis J

Bunu bir LINQ ifadesinde nasıl kullanırsınız? Yeniden kullanılabilir bir Where cümlesi olarak bunun gibi bir şey yapmak istiyorum ama uygulamakta zorlanıyorum.
Zorgarath

4
DÜZENLEME: boşver, şöyle olurdu:context.Where(IsSatisfied())
Zorgarath

Anahtar bölüm: "Entity Framework, sorgusunun bir parçası olarak C # kodunuzu gerçekten çalıştıramaz."
Alper

1

Bu kodda aynı hatayı aldım:

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

bu tam olarak hataydı:

System.NotSupportedException: 'LINQ to Entities,' Boolean Exists (System.Predicate`1 [conector_gp.Models.almacenes_por_sucursal]) 'yöntemini tanımıyor ve bu yöntem bir mağaza ifadesine çevrilemez.'

Bu şekilde çözdüm:

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

Tablomun önüne bir .ToList () ekledim , bu Varlık ve linq kodunu ayırıyor ve bir sonraki linq ifademin çevrilmesini engelliyor

NOT: Bu çözüm optimal değildir, çünkü varlık filtrelemesinden kaçınır ve tüm tabloyu belleğe yükler


1
Çoğu zaman bu en kolay çözümdür, ancak tüm nesneyi yüklememek için genellikle .ToList () öğesinden önce sadece ihtiyacım olan şeyle anonim bir seçim yapıyorum ... xx. (X => new {x.Id, x.DateTimeUpdate }). ToList (). (X => new {x.Id, DateTimeUpdate = x.DateTimeUpdate.ToString ("gg / MM / yyyy")})
Diógenes

0

Biri VB.Net cevabı arıyorsanız (başlangıçta olduğum gibi), işte burada:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.