ฉันต้องการชี้แจงบางสิ่งเนื่องจากคำตอบที่ขัดแย้งกันดูเหมือนจะเกิดขึ้น
(1) IQueryableขยายIEnumerableส่วนต่อประสาน (คุณสามารถส่งIQueryableสิ่งที่คาดหวังIEnumerableโดยไม่มีข้อผิดพลาด)
(2) ทั้งคู่IQueryableและIEnumerableLINQ พยายามทำการโหลดอย่างเกียจคร้านเมื่อวนซ้ำชุดผลลัพธ์ (โปรดทราบว่าการใช้งานสามารถเห็นได้ในวิธีการขยายส่วนต่อประสานสำหรับแต่ละประเภท)
ในคำอื่น ๆIEnumerablesไม่ได้เป็นเพียง "ในหน่วยความจำ" IQueryablesไม่ได้ถูกเรียกใช้งานบนฐานข้อมูลเสมอไป IEnumerableจะต้องโหลดสิ่งต่าง ๆ ลงในหน่วยความจำ (เมื่อดึงออกมาอาจเป็นไปอย่างขี้เกียจ) เพราะไม่มีผู้ให้บริการข้อมูลที่เป็นนามธรรม IQueryablesพึ่งพาผู้ให้บริการที่เป็นนามธรรม (เช่น LINQ-to-SQL) แม้ว่าสิ่งนี้อาจเป็นผู้ให้บริการในหน่วยความจำ. NET
ตัวอย่างการใช้งาน
(a) ดึงรายการบันทึกIQueryableจากบริบทของ EF (ไม่มีบันทึกอยู่ในหน่วยความจำ)
(ข) ผ่านไปยังมุมมองที่มีรูปแบบเป็นIQueryable IEnumerable(ถูกต้องIQueryableขยายIEnumerable )
(c) วนซ้ำและเข้าถึงระเบียนของเอนทิตีลูกและคุณสมบัติของชุดข้อมูลจากมุมมอง (อาจทำให้เกิดข้อยกเว้น!)
ปัญหาที่เป็นไปได้
(1) IEnumerableความพยายามโหลดขี้เกียจและบริบทข้อมูลของคุณหมดอายุ มีข้อผิดพลาดเกิดขึ้นเนื่องจากไม่มีผู้ให้บริการอีกต่อไป
(2) พร็อกซีเอนทิตีของ Entity Framework เปิดใช้งาน (ค่าเริ่มต้น) และคุณพยายามเข้าถึงวัตถุที่เกี่ยวข้อง (เสมือน) ที่มีบริบทข้อมูลที่หมดอายุ เช่นเดียวกับ (1)
(3) ชุดผลลัพธ์ที่ใช้งานอยู่หลายชุด (MARS) หากคุณกำลังวนซ้ำIEnumerableในforeach( var record in resultSet )บล็อกและพยายามเข้าถึงพร้อมกันrecord.childEntity.childPropertyคุณอาจลงเอยด้วย MARS เนื่องจากการโหลดชุดข้อมูลและเอนทิตีสัมพันธ์ สิ่งนี้จะทำให้เกิดข้อยกเว้นหากไม่ได้เปิดใช้งานในสตริงการเชื่อมต่อของคุณ
สารละลาย
- ฉันพบว่าการเปิดใช้งาน MARS ในสตริงการเชื่อมต่อนั้นใช้งานไม่ได้ ฉันขอแนะนำให้คุณหลีกเลี่ยง MARS เว้นแต่จะมีความเข้าใจและต้องการอย่างชัดเจน
ดำเนินการค้นหาและจัดเก็บผลลัพธ์โดยการเรียกใช้resultList = resultSet.ToList() นี่เป็นวิธีที่ตรงไปตรงมาที่สุดในการรับรองเอนทิตีของคุณในหน่วยความจำ
ในกรณีที่คุณกำลังเข้าถึงหน่วยงานที่เกี่ยวข้องคุณอาจต้องใช้บริบทข้อมูล ทั้งที่หรือคุณสามารถปิดผู้รับมอบฉันทะนิติบุคคลและชัดเจนหน่วยงานที่เกี่ยวข้องจากคุณIncludeDbSet