วิธีการเข้าร่วมกลุ่มใน. NET Core 3.0 Entity Framework


13

ด้วยการเปลี่ยนแปลงใน. NET Core 3.0 ฉันได้รับ

... NavigationExpanding ExpressionVisitor 'ล้มเหลว สิ่งนี้อาจบ่งบอกถึงข้อบกพร่องหรือข้อ จำกัด ใน EF Core ดู https://go.microsoft.com/fwlink/?linkid=2101433สำหรับข้อมูลรายละเอียดเพิ่มเติม) ---> System.InvalidOperationException: การประมวลผลนิพจน์ LINQ 'GroupJoin, ...

นี่เป็นแบบสอบถามที่ง่ายมากดังนั้นจึงต้องมีวิธีดำเนินการใน. NET CORE 3.0:

 var queryResults1 = await patients
            .GroupJoin(
                _context.Studies,
                p => p.Id,
                s => s.Patient.Id,
                (p, studies) => new 
                {
                    p.DateOfBirth,
                    p.Id,
                    p.Name,
                    p.Sex,
                   Studies =studies.Select(s1=>s1)
                }
            )
            .AsNoTracking().ToListAsync();

โดยทั่วไปฉันกำลังมองหาคำสั่ง Linq (หรือไวยากรณ์ของวิธีการข้างต้น) ซึ่งจะเข้าร่วมการศึกษาไปยังผู้ป่วยและตั้งค่าการศึกษาเป็นรายการว่างหรือโมฆะหากไม่มีการศึกษาสำหรับผู้ป่วยที่ได้รับ

ความคิดใด ๆ สิ่งนี้ทำงานใน. NET Core 2.2 นอกจากนี้ลิงค์ MSFT ด้านบนยังกล่าวอีกว่าการเปลี่ยนแปลงการทำลายคีย์นั้นเกี่ยวข้องกับการประเมินฝั่งไคลเอ็นต์และหลีกเลี่ยงการที่แบบสอบถามที่สร้างขึ้นอ่านตารางทั้งหมดซึ่งจะต้องเข้าร่วมหรือกรองฝั่งไคลเอ็นต์ อย่างไรก็ตามด้วยแบบสอบถามง่ายๆนี้การเข้าร่วมควรเป็นฝั่งเซิร์ฟเวอร์ที่ทำได้

คำตอบ:


11

ตามที่กล่าวไว้ที่นี่คุณกำลังพยายามสืบค้นที่ฐานข้อมูลไม่สนับสนุน EF Core 2 ใช้การประเมินฝั่งไคลเอ็นต์เพื่อให้โค้ดของคุณใช้งานได้ แต่ EF Core 3 ปฏิเสธเนื่องจากความสะดวกด้านฝั่งไคลเอ็นต์มีค่าใช้จ่ายในการแก้ไขปัญหาประสิทธิภาพการทำงานที่ยากต่อการดีบักเมื่อชุดข้อมูลเพิ่มขึ้น

คุณสามารถใช้การใช้งานทางด้านซ้ายเข้าร่วมการศึกษาผู้ป่วยและกลุ่มด้วยตนเองDefaultIfEmptyToLookup

var query =
    from p in db.Patients
    join s in db.Studies on p.Id equals s.PatientId into studies
    from s in studies.DefaultIfEmpty()
    select new { Patient = p, Study = s };

var grouping = query.ToLookup(e => e.Patient); // Grouping done client side

ตัวอย่างข้างต้นคว้าเอนทิตี้แบบเต็มของผู้ป่วยและการศึกษา แต่คุณสามารถเลือกคอลัมน์เชอร์รี่แทน หากข้อมูลที่คุณต้องการจากผู้ป่วยมีขนาดใหญ่เกินไปที่จะทำซ้ำสำหรับการศึกษาแต่ละครั้งในแบบสอบถามแบบใช้ร่วมกันให้เลือกเฉพาะ ID ผู้ป่วยเท่านั้นการสอบถามข้อมูลส่วนที่เหลือของผู้ป่วยในแบบสอบถามที่ไม่ได้เข้าร่วมแยกต่างหาก


2
ตอบงาน! ฉันเดาว่ายังมีงานที่ต้องทำในตัวแปลแบบสอบถาม แบบสอบถามแบบนี้ควรแปลได้ง่าย ไม่ควรมีปัญหาเรื่องประสิทธิภาพสำหรับการรวมกลุ่มอย่างง่ายของ 2 ตารางเนื่องจากชุดข้อมูลเพิ่มขึ้นโดยสมมติว่า FK / ดัชนีถูกต้อง ฉันสงสัยว่าหลายคนจะมีปัญหานี้การเข้าร่วมกลุ่มตารางที่ 2 เป็นคำถามที่ค่อนข้างมาตรฐานและใช้บ่อย
shelbypereira

@ she72 ฉันเห็นด้วย ดูเหมือนว่าปัญหาเกิดจากความแตกต่างในวิธีที่ LINQ และ SQL ใช้คำหลัก "กลุ่ม" EF Core ควรแปล LINQ groupbyเป็นซ้ายเข้าร่วมซึ่งการทำเช่นนั้นจะไม่ดึงแถวมากกว่าที่คาดไว้ ฉันโพสต์ความคิดเห็นตาม
Edward Brey

ฉันมีคำถามติดตามฉันยังคงพยายามที่จะเข้าใจว่าทำไมการจัดกลุ่มสำหรับแบบสอบถามชนิดนี้จำเป็นต้องทำในฝั่งไคลเอ็นต์ดูเหมือนว่าจะมีข้อ จำกัด ของกรอบ LINQ ใหม่ สำหรับกรณีข้างต้นฉันไม่เห็นความเสี่ยงใด ๆ ที่ทำให้การดำเนินการด้านลูกค้าช้าลงในรูปแบบที่ไม่คาดคิด คุณช่วยอธิบายได้ไหม
shelbypereira

1
และตามการติดตามต่อไปข้อกังวลหลักคือ: ในแบบสอบถามที่ปรับปรุงใหม่ของคุณซึ่งกลุ่มลูกค้าด้านถ้าฉันมี 1,000 การศึกษาต่อผู้ป่วยฉันจะโหลดผู้ป่วยแต่ละราย 1,000 ครั้งจากฐานข้อมูลหรือไม่ มีทางเลือกอื่นที่จะบังคับให้งานนี้ทำในฐานข้อมูลและส่งคืนผลลัพธ์ที่จัดกลุ่มหรือไม่
shelbypereira

1
@ shev72 การจัดกลุ่มฐานข้อมูลเท่านั้นที่เกี่ยวข้องกับการรวมตัวอย่างเช่นแบบสอบถามของผู้ป่วยที่มีจำนวนการศึกษาต่อผู้ป่วย ฐานข้อมูลส่งคืนชุดข้อมูลรูปสี่เหลี่ยมผืนผ้าเสมอ การจัดกลุ่มแบบลำดับชั้นจะต้องมีการแต่งโดยลูกค้า คุณอาจจะมองไปที่มันเป็นการประเมินผลฝั่งไคลเอ็นต์หรือเป็นส่วนหนึ่งของการออม ในการจัดกลุ่มตามลำดับชั้นข้อมูลนิติบุคคลหลักจะถูกทำซ้ำแม้ว่าจะไม่ได้รับการสอบถามซ้ำอีกครั้ง
Edward Brey

0

มีปัญหาเดียวกันและต่อสู้กับมันมาก ปรากฎว่า. net Core 3.0 ไม่รองรับการเข้าร่วมหรือ Groupjoin ในไวยากรณ์วิธีการ (ยัง?) ส่วนที่สนุกคือว่ามันทำงานในไวยากรณ์แบบสอบถาม

ลองสิ่งนี้มันเป็นไวยากรณ์เคียวรีที่มีไวยากรณ์ของเมธอดเล็กน้อย นี่แปลว่าแบบสอบถาม SQL ที่ถูกต้องซึ่งมีการรวมภายนอกด้านซ้ายที่ดีและถูกประมวลผลบนฐานข้อมูล ฉันไม่มีโมเดลของคุณดังนั้นคุณต้องตรวจสอบไวยากรณ์ด้วยตัวเอง ....

var queryResults1 = 
    (from p in _context.patients
    from s in _context.Studies.Where(st => st.PatientId == p.Id).DefaultIfEmpty()
    select new
    {
        p.DateOfBirth,
        p.Id,
        p.Name,
        p.Sex,
        Studies = studies.Select(s1 => s1)
    }).ToListAsync();

โดยวิธีการเข้าร่วมและ GroupJoin ด้วยวิธีการ syntac DO ทำงานกับกรอบที่ไม่ใช่หลักและ EF และแปลให้กับการสืบค้นที่ถูกต้องซึ่งเป็นฝั่งเซิร์ฟเวอร์ที่ให้ความเป็นส่วนตัว
hwmaat

1
การศึกษาคืออะไรในการศึกษาเลือก (s1 => s1)
Ankur Arora

แบบจำลองไม่รวมอยู่ในคำถามดังนั้นฉันไม่ทราบรูปแบบการศึกษา ฉันเดาได้ดีที่สุดว่านี่เป็นคอลเล็กชันเสมือนจริงในโมเดล
hwmaat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.