Include () ทำอะไรใน LINQ?


96

ฉันพยายามทำการวิจัยมากมาย แต่ฉันเป็นคนชอบ db มากกว่าดังนั้นแม้แต่คำอธิบายใน MSDN ก็ไม่สมเหตุสมผลกับฉันเลย ใครก็ได้โปรดอธิบายและให้ตัวอย่างบางส่วนเกี่ยวกับInclude()คำแถลงในข้อกำหนดของSQLสืบค้น


พื้นฐานมากฉันรู้เพียงตัวเลือกง่ายๆที่ไหนเรียงลำดับโดยตัวดำเนินการรวมบางตัว ฉันไม่ได้ลองเข้าร่วมใน LINQ หรือรวม เป้าหมายสูงสุดของฉันคือสามารถเขียนข้อความค้นหา LINQ เหล่านี้ใหม่เป็น SQL ได้
CJ

คำตอบ:


169

สมมติว่าคุณต้องการรับรายชื่อลูกค้าทั้งหมดของคุณ:

var customers = context.Customers.ToList();

และสมมติว่าแต่ละCustomerออบเจ็กต์มีการอ้างอิงถึงชุดของOrdersมันและแต่ละชิ้นOrderมีการอ้างอิงLineItemsซึ่งอาจอ้างถึง a Product.

อย่างที่คุณเห็นการเลือกออบเจ็กต์ระดับบนสุดที่มีเอนทิตีที่เกี่ยวข้องจำนวนมากอาจส่งผลให้คิวรีต้องดึงข้อมูลจากหลายแหล่ง ในการวัดประสิทธิภาพInclude()ช่วยให้คุณระบุว่าควรอ่านเอนทิตีที่เกี่ยวข้องใดจากฐานข้อมูลโดยเป็นส่วนหนึ่งของแบบสอบถามเดียวกัน

เมื่อใช้ตัวอย่างเดียวกันสิ่งนี้อาจทำให้เกิดส่วนหัวคำสั่งซื้อที่เกี่ยวข้องทั้งหมด แต่ไม่มีเรกคอร์ดอื่น ๆ :

var customersWithOrderDetail = context.Customers.Include("Orders").ToList();

เป็นจุดสุดท้ายตั้งแต่คุณขอ SQL คำสั่งแรกที่ไม่มีไม่Include()สามารถสร้างคำสั่งง่ายๆ:

SELECT * FROM Customers;

คำสั่งสุดท้ายที่เรียกInclude("Orders")อาจมีลักษณะดังนี้:

SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;

1
ขอบคุณ. จากตัวอย่างของคุณฉันสามารถพูดได้ว่าฉันต้องการรวมLineItemsและProductsแบบสอบถาม LINQ ควรมีลักษณะดังนี้: var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();?
CJ

2
ได้คุณสามารถเชื่อมโยงการเรียกหลาย ๆ สายInclude()เพื่อจับวัตถุตาม "เส้นทาง" ที่แตกต่างกันได้ หากคุณต้องการให้ออบเจ็กต์อยู่ในเส้นทางเดียวกันคุณจะต้องทำการเรียกเพียงครั้งเดียวที่ระบุเส้นทางทั้งหมด เนื่องจากLineItemsและProductsไม่แชร์องค์ประกอบเส้นทางใด ๆ คุณจึงต้องมีการโทรแยก
Yuck

จำเป็นต้องใช้รวมหรือไม่ ฉันค่อนข้างมั่นใจว่าฉันได้แก้ปัญหาที่ฉันสามารถหาวัตถุที่เกี่ยวข้องได้โดยไม่ต้องใช้มัน
Jepzen

@Jepzen มันขึ้นอยู่กับว่าคุณกำลังใช้เอนทิตีแบบขี้เกียจหรือไม่
Yuck

@ แย่ฉันเชื่อว่าสิ่งนี้ใช้ได้ผลเมื่อคุณใช้การโหลดแบบขี้เกียจในกรณีที่ต้องการโหลดคุณไม่จำเป็นต้องใช้คำสั่ง "รวม" แต่สิ่งนี้จะส่งผลให้เกิดปัญหาด้านประสิทธิภาพอย่างแน่นอน โปรดแก้ไขฉันในเรื่องนี้
sam

27

ฉันแค่อยากจะเพิ่มว่า "รวม" เป็นส่วนหนึ่งของการโหลดอย่างกระตือรือร้น มีอธิบายไว้ในบทช่วยสอน Entity Framework 6 โดย Microsoft นี่คือลิงค์: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the -entity-framework-in-an-asp-net-mvc-application


ตัดตอนมาจากหน้าที่เชื่อมโยง:

นี่คือหลายวิธีที่ Entity Framework สามารถโหลดข้อมูลที่เกี่ยวข้องลงในคุณสมบัติการนำทางของเอนทิตี:

ขี้เกียจโหลด. เมื่ออ่านเอนทิตีเป็นครั้งแรกข้อมูลที่เกี่ยวข้องจะไม่ถูกเรียกคืน อย่างไรก็ตามในครั้งแรกที่คุณพยายามเข้าถึงคุณสมบัติการนำทางข้อมูลที่จำเป็นสำหรับคุณสมบัติการนำทางนั้นจะถูกดึงโดยอัตโนมัติ สิ่งนี้ส่งผลให้มีการสืบค้นหลายรายการที่ส่งไปยังฐานข้อมูล - หนึ่งรายการสำหรับเอนทิตีเองและอีกครั้งในแต่ละครั้งที่ต้องดึงข้อมูลที่เกี่ยวข้องสำหรับเอนทิตี คลาส DbContext เปิดใช้งานการโหลดแบบขี้เกียจตามค่าเริ่มต้น

กำลังโหลด เมื่ออ่านเอนทิตีข้อมูลที่เกี่ยวข้องจะถูกดึงมาด้วย โดยทั่วไปจะส่งผลให้มีคิวรีการรวมเดียวที่ดึงข้อมูลทั้งหมดที่จำเป็น คุณระบุการโหลดที่ต้องการโดยใช้Includeวิธีการ

กำลังโหลดอย่างชัดเจน สิ่งนี้คล้ายกับการโหลดแบบขี้เกียจยกเว้นว่าคุณดึงข้อมูลที่เกี่ยวข้องในโค้ดอย่างชัดเจน จะไม่เกิดขึ้นโดยอัตโนมัติเมื่อคุณเข้าถึงคุณสมบัติการนำทาง คุณโหลดข้อมูลที่เกี่ยวข้องด้วยตนเองโดยรับรายการตัวจัดการสถานะอ็อบเจ็กต์สำหรับเอนทิตีและเรียกเมธอด Collection.Load สำหรับคอลเลกชันหรือเมธอด Reference.Load สำหรับคุณสมบัติที่เก็บเอนทิตีเดียว (ในตัวอย่างต่อไปนี้หากคุณต้องการโหลดคุณสมบัติการนำทางของผู้ดูแลระบบคุณจะแทนที่Collection(x => x.Courses)ด้วยReference(x => x.Administrator)) โดยทั่วไปคุณจะใช้การโหลดแบบชัดแจ้งเฉพาะเมื่อคุณปิดการโหลดแบบขี้เกียจ

เนื่องจากไม่ได้ดึงค่าคุณสมบัติในทันทีการโหลดแบบขี้เกียจและการโหลดแบบชัดแจ้งจึงเรียกอีกอย่างว่าการโหลดแบบรอการตัดบัญชี


3
ยินดีต้อนรับสู่ SO =) เป็นเพียงข้อเสนอแนะ แต่เมื่อคุณตอบคำถามเช่นนั้นให้ใส่ข้อมูลโค้ดด้วยหากทำได้ ลิงก์อาจตายไปอย่างน่าเสียดาย
The_Cthulhu_Kid

2

คิดว่าเป็นการบังคับใช้ Eager-Loading ในสถานการณ์ที่รายการย่อยของคุณจะขี้เกียจโหลด

Query EF กำลังส่งไปยังฐานข้อมูลจะให้ผลลัพธ์ที่ใหญ่กว่าในตอนแรก แต่ในการเข้าถึงจะไม่มีการสอบถามติดตามเมื่อเข้าถึงรายการที่รวมอยู่

ในทางกลับกันหากไม่มี EF จะดำเนินการค้นหาแยกในภายหลังเมื่อคุณเข้าถึงรายการย่อยเป็นครั้งแรก

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