ความแตกต่างระหว่าง IQueryable กับ IEnumerable คืออะไร


150

ฉันสับสนกับความแตกต่าง ค่อนข้างใหม่สำหรับ. Net ฉันรู้ว่าฉันสามารถสืบค้นIEnumerablesโดยใช้ส่วนขยาย Linq แล้วนี่คืออะไรIQueryableและมันแตกต่างกันอย่างไร


ดูเพิ่มเติมความแตกต่างระหว่าง IQueryable [T] และ IEnumerable [T] คืออะไร? ที่ทับซ้อนกับคำถามนี้

คำตอบ:


186

IEnumerable<T>Tแสดงให้เห็นถึงเคอร์เซอร์ไปข้างหน้าอย่างเดียว NET 3.5 วิธีการเพิ่มส่วนขยายที่รวมLINQ standard query operatorsชอบWhereและFirstมีผู้ประกอบการใด ๆ Func<T>ที่จำเป็นต้องมีภาคหรือฟังก์ชันที่ไม่ระบุชื่อการ

IQueryable<T>ใช้ตัวดำเนินการแบบสอบถามมาตรฐาน LINQ เดียวกัน แต่ยอมรับExpression<Func<T>>สำหรับเพรดิเคตและฟังก์ชันที่ไม่ระบุชื่อ Expression<T>เป็นทรีนิพจน์ที่คอมไพล์ซึ่งเป็นเวอร์ชันที่เสียของเมธอด ("คอมไพล์ครึ่ง" หากคุณต้องการ) ที่สามารถแยกวิเคราะห์โดยผู้ให้บริการที่สามารถสืบค้นได้และใช้ตามนั้น

ตัวอย่างเช่น:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

ในบล็อกแรกx => x.Age > 18เป็นวิธีที่ไม่ระบุชื่อ ( Func<Person, bool>) ซึ่งสามารถดำเนินการได้เหมือนกับวิธีอื่นใด Enumerable.Whereจะดำเนินการวิธีการครั้งเดียวสำหรับแต่ละบุคคลyielding trueค่าซึ่งวิธีการส่งกลับ

ในบล็อกที่สองx => x.Age > 18เป็นต้นไม้แสดงออก ( Expression<Func<Person, bool>>) ซึ่งสามารถคิดได้ว่าเป็น "เป็นคุณสมบัติ 'อายุ'> 18"

สิ่งนี้อนุญาตให้สิ่งต่าง ๆ เช่น LINQ-to-SQL มีอยู่ได้เนื่องจากสามารถแยกวิเคราะห์แผนผังของนิพจน์และแปลงเป็น SQL ที่เทียบเท่าได้ และเนื่องจากผู้ให้บริการไม่จำเป็นต้องดำเนินการจนกว่าIQueryableจะแจกแจง (ดำเนินการIEnumerable<T>หลังจากทั้งหมด) จึงสามารถรวมตัวดำเนินการแบบสอบถามหลายรายการ (ในตัวอย่างด้านบนWhereและFirstOrDefault) เพื่อสร้างตัวเลือกที่ชาญฉลาดเกี่ยวกับวิธีดำเนินการแบบสอบถามทั้งหมดกับข้อมูลพื้นฐาน แหล่งที่มา (เช่นใช้SELECT TOP 1ใน SQL)

ดู:


1
คำตอบสั้น ๆ สวย ๆ
ashveli

83

ในชีวิตจริงถ้าคุณใช้ ORM เช่น LINQ-to-SQL

  • ถ้าคุณสร้างการIQueryableค้นหาอาจถูกแปลงเป็น sql และเรียกใช้บนเซิร์ฟเวอร์ฐานข้อมูล
  • หากคุณสร้างIEnumerableแถวจากนั้นแถวทั้งหมดจะถูกดึงเข้าสู่หน่วยความจำในฐานะวัตถุก่อนเรียกใช้แบบสอบถาม

ในทั้งสองกรณีหากคุณไม่ได้โทรหา A ToList()หรือToArray()แบบสอบถามจะถูกดำเนินการทุกครั้งที่มีการใช้งานดังนั้นคุณจะต้องIQueryableกรอกข้อมูลลงในกล่องรายการ 4 รายการจากนั้นแบบสอบถามจะทำงานกับฐานข้อมูล 4 ครั้ง

นอกจากนี้หากคุณขยายการสอบถามของคุณ:

q.Select(x.name = "a").ToList()

จากนั้นด้วยIQueryableSQL ที่สร้างขึ้นจะมีwhere name = "a"แต่ด้วยIEnumerableบทบาทอื่น ๆ อีกมากมายจะถูกดึงกลับมาจากฐานข้อมูลแล้วการx.name = "a"ตรวจสอบจะทำโดย. NET


"ข้อความค้นหาอาจถูกแปลงเป็น sql": ฉันไม่ได้รับข้อความ 'อาจเป็น' นอกจากนี้ถ้าฉันมี IEnumerable และสร้าง 'chain chain' ดังนั้น (ชัด) ซึ่งแตกต่างจาก IQueryable จะไม่ถูกแปลเป็นแบบสอบถาม SQL ที่ 'เพิ่มประสิทธิภาพ' เพียงต้องการยืนยันความหมายเมื่อคุณพูดว่า 'ทุกแถวจะถูกดึงเข้าสู่หน่วยความจำ' ให้เราบอกว่าฉันมีสองที่อนุประโยคแล้วสิ่งอันดับของเอนทิตีทั้งหมดจะถูกดึงเข้าไปในหน่วยความจำก่อนจากนั้นการกรองปกติ 'ในหน่วยความจำ' จะเกิดขึ้น?
Vaibhav

36

"ความแตกต่างหลักคือวิธีการขยายที่กำหนดไว้สำหรับ IQueryable ใช้วัตถุ Expression แทนวัตถุ Func ซึ่งหมายถึงผู้รับมอบสิทธิ์ที่ได้รับคือต้นไม้แสดงอารมณ์แทนวิธีการที่จะเรียกใช้ IEnumerable นั้นยอดเยี่ยมสำหรับการทำงานกับคอลเลกชันในหน่วยความจำ สำหรับแหล่งข้อมูลระยะไกลเช่นฐานข้อมูลหรือบริการเว็บ "

ที่มา: ที่นี่


19

IEnumerable IEnumerable เหมาะสมที่สุดสำหรับการทำงานกับการรวบรวมในหน่วยความจำ IEnumerable ไม่ย้ายระหว่างรายการมันเป็นเพียงการรวบรวมเท่านั้น

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

ดังนั้นเมื่อคุณต้องย้ำผ่านคอลเลกชันในหน่วยความจำใช้ IEnumerable ถ้าคุณต้องการจัดการกับคอลเลกชันเช่นชุดข้อมูลและแหล่งข้อมูลอื่น ๆ ใช้ IQueryable


11

ความแตกต่างที่สำคัญคือ IEnumerable จะแจกแจงองค์ประกอบทั้งหมดตลอดเวลาในขณะที่ IQueryable จะแจกแจงองค์ประกอบหรือทำสิ่งอื่น ๆ ตามแบบสอบถาม แบบสอบถามคือ Expression (การแทนข้อมูลของรหัส. Net) ซึ่ง IQueryProvider ต้องสำรวจ / ตีความ / คอมไพล์ / อะไรก็ตามเพื่อสร้างผลลัพธ์

การมีนิพจน์แบบสอบถามให้ข้อดีสองประการ

ข้อดีแรกคือการเพิ่มประสิทธิภาพ เนื่องจากโมดิฟายเออร์เช่น 'ที่ไหน' จึงรวมอยู่ในนิพจน์แบบสอบถาม IQueryProvider จึงสามารถใช้การปรับให้เหมาะสมอย่างอื่นไม่ได้ แทนที่จะส่งคืนองค์ประกอบทั้งหมดแล้วละทิ้งองค์ประกอบส่วนใหญ่เนื่องจากประโยค 'Where' ผู้ให้บริการสามารถใช้ตารางแฮชเพื่อค้นหารายการด้วยคีย์ที่กำหนด

ข้อได้เปรียบที่สองคือความยืดหยุ่น เนื่องจากการแสดงออกเป็นโครงสร้างข้อมูลที่อธิบายได้คุณสามารถทำสิ่งต่าง ๆ เช่นซีเรียลคิวรี่ของคิวรีและส่งไปยังเครื่องรีโมต (เช่น linq-to-sql)



1

อันดับแรกคือ IEnumerable ที่พบใน System.Collections Namespace ในขณะที่ IQueryable นั้นจะอยู่ใน System.Linq Namespace หากคุณใช้ IEnumerable เมื่อทำการสืบค้นข้อมูลจากการรวบรวมข้อมูลในหน่วยความจำเช่น List, Array collection เป็นต้นและเมื่อทำการสืบค้นข้อมูลจากหน่วยความจำนอก (เช่นฐานข้อมูลระยะไกลบริการ) คุณจะได้ใช้ IQueryable เนื่องจากขณะทำการสืบค้นข้อมูลจากฐานข้อมูล IEnumerable จะเรียกใช้งานแบบสอบถามแบบใช้เลือกข้อมูลในฝั่งเซิร์ฟเวอร์โหลดข้อมูลในหน่วยความจำในฝั่งไคลเอ็นต์แล้วกรองข้อมูล ดังนั้นทำงานได้มากขึ้นและช้าลง ในขณะที่การสืบค้นข้อมูลจากฐานข้อมูล IQueryable ดำเนินการแบบสอบถามแบบใช้เลือกข้อมูลทางฝั่งเซิร์ฟเวอร์พร้อมตัวกรองทั้งหมด ดังนั้นการทำงานน้อยลงและกลายเป็นรวดเร็ว

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