LINQ to Entities ไม่รู้จักเมธอด


116

ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อพยายามทำแบบสอบถาม linq:

LINQ เป็นเอนทิตีไม่รู้จักเมธอด '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;
}

โปรดแจ้งให้เราทราบหากคุณต้องการข้อมูลเพิ่มเติม

ขอบคุณมาก,

Annelie


ตรวจสอบคำตอบนี้
Eranga

จะตรวจสอบสิ่งนี้เช่นกันขอบคุณ!
annelie

1
คงจะดีไม่น้อยที่ได้เห็นว่าคุณใช้งานFind()อย่างไรเมื่อใช้IsSatisfied()ภายใน
Alisson

คำตอบ:


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/…
Chris Hayes

2
การส่งคืนโครงสร้างExpression<Func<T,type>>เป็นวิธีที่ดีมากสำหรับสิ่งนี้
Travis J

คุณจะใช้สิ่งนี้ในนิพจน์ LINQ อย่างไร ฉันต้องการทำสิ่งนี้เป็นประโยค Where ที่ใช้งานได้อีกครั้ง แต่ฉันกำลังดิ้นรนกับการนำไปใช้
Zorgarath

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 เลือก (x => ใหม่ {x.Id, x.DateTimeUpdate }). ToList (). เลือก (x => new {x.Id, DateTimeUpdate = x.DateTimeUpdate ToString ("dd / MM / yyyy")})
Diógenes

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.