ความแตกต่างระหว่างIQueryable<T>และIEnumerable<T>คืออะไร?
ดูเพิ่มเติมความแตกต่างระหว่าง IQueryable และ IEnumerableที่ทับซ้อนกับคำถามนี้คืออะไร
ความแตกต่างระหว่างIQueryable<T>และIEnumerable<T>คืออะไร?
ดูเพิ่มเติมความแตกต่างระหว่าง IQueryable และ IEnumerableที่ทับซ้อนกับคำถามนี้คืออะไร
คำตอบ:
แรกของทุกขยายอินเตอร์เฟซดังนั้นสิ่งที่คุณสามารถทำได้ด้วย "ธรรมดา" คุณยังสามารถทำอะไรกับIQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>
IEnumerable<T>เพียงแค่มีGetEnumerator()วิธีการที่ส่งกลับEnumerator<T>ที่คุณสามารถเรียกมันMoveNext()วิธีการย้ำถึงลำดับของT
อะไรIQueryable<T>ได้ว่าIEnumerable<T> ไม่เป็นสองคุณสมบัติโดยเฉพาะอย่างยิ่งหนึ่งที่ชี้ไปยังผู้ให้บริการแบบสอบถาม (เช่น LINQ เพื่อให้บริการ SQL) และชี้อีกครั้งเพื่อให้การแสดงออกแบบสอบถามที่เป็นตัวแทนของIQueryable<T>วัตถุเป็นรันไทม์ทะลุต้นไม้ไวยากรณ์นามธรรมที่สามารถ เข้าใจโดยผู้ให้บริการแบบสอบถามที่กำหนด (ส่วนใหญ่คุณไม่สามารถให้ LINQ กับนิพจน์ SQL แก่ผู้ให้บริการ LINQ to Entities ได้โดยไม่มีข้อยกเว้นเกิดขึ้น)
นิพจน์สามารถเป็นนิพจน์คงที่ของวัตถุเองหรือโครงสร้างที่ซับซ้อนมากขึ้นของชุดตัวดำเนินการแบบสอบถามและตัวถูกดำเนินการ ตัวให้บริการแบบสอบถามIQueryProvider.Execute()หรือIQueryProvider.CreateQuery()วิธีการที่เรียกว่ามีการแสดงออกผ่านไปแล้วผลIQueryableตอบแทนแบบสอบถามหรืออื่นจะถูกส่งกลับตามลำดับ
AsQueryable()มันจะทำการส่ง enumerable ให้กับ queryable และคืนมันถ้ามันใช้IQueryableอินเตอร์เฟสหรือไม่ก็มันจะล้อมรอบด้วย a ConstantExpressionซึ่งถูกอ้างถึงในEnumerableQueryวัตถุที่ถูกส่งคืน
ข้อแตกต่างหลักคือตัวดำเนินการ LINQ สำหรับIQueryable<T>นำExpressionวัตถุแทนผู้รับมอบสิทธิ์ซึ่งหมายถึงตรรกะคิวรีแบบกำหนดเองที่ได้รับเช่นตัวเลือกเพรดิเคตหรือตัวเลือกค่าอยู่ในรูปแบบของแผนภูมินิพจน์แทนผู้แทนไปยังวิธีการ
IEnumerable<T> ดีมากสำหรับการทำงานกับลำดับที่ซ้ำในหน่วยความจำ แต่ IQueryable<T> ช่วยให้หน่วยความจำไม่เพียงพอเช่นแหล่งข้อมูลระยะไกลเช่นฐานข้อมูลหรือบริการบนเว็บโดยที่การดำเนินการของแบบสอบถามจะถูกดำเนินการ"อยู่ระหว่างดำเนินการ"โดยทั่วไปสิ่งที่จำเป็นต้องมีคือรหัส (เป็นรหัส) เพื่อดำเนินการแต่ละส่วนของแบบสอบถาม
ในกรณีที่การดำเนินการจะดำเนินการนอกกระบวนการตรรกะของแบบสอบถามจะต้องมีการแสดงในข้อมูลเช่นผู้ให้บริการ LINQ สามารถแปลงเป็นรูปแบบที่เหมาะสมสำหรับการดำเนินการออกจากหน่วยความจำ - ไม่ว่าจะเป็นแบบสอบถาม LDAP SQL หรืออะไรก็ตาม
เพิ่มเติมใน:
IEnumerable<T>และIQueryable<T>IEnumerable<T>เทียบกับIQueryable<T> "IEnumerable, IQueryable, IObservableและIQbservable
นี่เป็นวิดีโอที่ดีใน youtubeซึ่งแสดงให้เห็นว่าอินเทอร์เฟซเหล่านี้แตกต่างกันอย่างไรน่าดู
ด้านล่างมีคำตอบยาว ๆ สำหรับคำอธิบาย
จุดสำคัญแรกที่ต้องจดจำคือIQueryableอินเทอร์เฟซที่สืบทอดมาจากIEnumerableดังนั้นสิ่งที่IEnumerableสามารถทำได้IQueryableสามารถทำได้

มีความแตกต่างมากมาย แต่ให้เราคุยกันเกี่ยวกับความแตกต่างที่ยิ่งใหญ่ซึ่งทำให้แตกต่างมากที่สุด IEnumerableอินเตอร์เฟสมีประโยชน์เมื่อโหลดคอลเล็กชันของคุณโดยใช้LINQหรือ Framework เอนทิตีและคุณต้องการใช้ตัวกรองกับคอลเลกชัน
พิจารณารหัสง่าย ๆ ด้านล่างซึ่งใช้IEnumerableกับกรอบงานเอนทิตี มันใช้Whereตัวกรองที่จะได้รับการบันทึกที่มีคือEmpId2
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
ที่นี่ตัวกรองจะถูกดำเนินการในฝั่งไคลเอ็นต์ที่เป็นIEnumerableรหัส ในคำอื่น ๆ ข้อมูลทั้งหมดจะถูกดึงข้อมูลจากฐานข้อมูลแล้วที่ลูกค้าสแกนและได้รับการบันทึกด้วยมีEmpId2

แต่ตอนนี้ดูโค้ดด้านล่างนี้เรามีการเปลี่ยนแปลงไปIEnumerable IQueryableมันสร้างแบบสอบถาม SQL ที่ฝั่งเซิร์ฟเวอร์และข้อมูลที่จำเป็นเท่านั้นที่ถูกส่งไปยังฝั่งไคลเอ็นต์
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

ดังนั้นความแตกต่างระหว่างIQueryableและIEnumerableเป็นเรื่องเกี่ยวกับที่ดำเนินการตรรกะตัวกรอง หนึ่งรันบนฝั่งไคลเอ็นต์และอีกหนึ่งรันบนฐานข้อมูล
ดังนั้นหากคุณทำงานกับการเก็บรวบรวมข้อมูลในหน่วยความจำเท่านั้นIEnumerableเป็นตัวเลือกที่ดี แต่ถ้าคุณต้องการสืบค้นข้อมูลที่เชื่อมต่อกับฐานข้อมูล `` IQueryable เป็นตัวเลือกที่ดีกว่าเพราะช่วยลดปริมาณการใช้งานเครือข่ายและใช้ภาษา SQL
IEnumerable: IEnumerable เหมาะสมที่สุดสำหรับการทำงานกับการรวบรวมในหน่วยความจำ (หรือแบบสอบถามแบบโลคัล) IEnumerable ไม่ย้ายระหว่างรายการมันเป็นเพียงการรวบรวมเท่านั้น
IQueryable: เหมาะสมที่สุดกับ IQueryable สำหรับแหล่งข้อมูลระยะไกลเช่นฐานข้อมูลหรือบริการบนเว็บ (หรือข้อความค้นหาระยะไกล) IQueryable เป็นคุณสมบัติที่ทรงพลังมากที่ช่วยให้สถานการณ์การดำเนินการรอการตัดบัญชีที่น่าสนใจหลากหลาย (เช่นการสอบถามเพจและการเรียงตามองค์ประกอบ)
ดังนั้นเมื่อคุณต้องทำซ้ำผ่านคอลเลกชันในหน่วยความจำให้ใช้ IEnumerable หากคุณต้องการจัดการกับคอลเลกชันเช่นชุดข้อมูลและแหล่งข้อมูลอื่น ๆ ให้ใช้ IQueryable
ในคำง่าย ๆ ความแตกต่างที่สำคัญอื่น ๆ คือ IEnumerable เรียกใช้แบบสอบถามแบบใช้เลือกข้อมูลในฝั่งเซิร์ฟเวอร์โหลดข้อมูลในหน่วยความจำในฝั่งไคลเอ็นต์แล้วกรองข้อมูลในขณะที่ IQueryable เรียกใช้แบบสอบถามแบบใช้เลือกข้อมูลบนฝั่งเซิร์ฟเวอร์พร้อมตัวกรองทั้งหมด
ในชีวิตจริงถ้าคุณใช้ ORM เช่น LINQ-to-SQL
ในทั้งสองกรณีหากคุณไม่ได้โทรหา A ToList()หรือToArray()แบบสอบถามจะถูกดำเนินการทุกครั้งที่มีการใช้งานดังนั้นคุณจะต้องIQueryable<T>กรอกข้อมูลลงในกล่องรายการ 4 รายการจากนั้นแบบสอบถามจะทำงานกับฐานข้อมูล 4 ครั้ง
นอกจากนี้หากคุณขยายขอบเขตการค้นหาของคุณ:
q.Where(x.name = "a").ToList()
จากนั้นด้วย IQueryable SQL ที่สร้างขึ้นจะมี“ โดยที่ name =“ a” แต่ด้วย IEnumerable บทบาทอีกมากมายจะถูกดึงกลับมาจากฐานข้อมูลจากนั้นการตรวจสอบ x.name =“ a” จะดำเนินการโดย. NET
IEnumerable อ้างถึงคอลเล็กชัน แต่ IQueryable เป็นเพียงแบบสอบถามและจะถูกสร้างขึ้นภายใน Expression Tree เราจะเรียกใช้แบบสอบถามนี้เพื่อรับข้อมูลจากฐานข้อมูล
ด้านล่างทดสอบขนาดเล็กพูดถึงอาจจะช่วยให้คุณเข้าใจแง่มุมหนึ่งของความแตกต่างระหว่างและIQueryable<T> IEnumerable<T>ฉันทำซ้ำคำตอบนี้จากโพสต์นี้ที่ฉันพยายามเพิ่มการแก้ไขในโพสต์ของคนอื่น
ฉันสร้างโครงสร้างต่อไปนี้ใน DB (สคริปต์ DDL):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
นี่คือสคริปต์แทรกเรคคอร์ด (สคริปต์ DML):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
ตอนนี้เป้าหมายของฉันคือการได้รับ 2 อันดับแรกจากEmployeeตารางในฐานข้อมูล ฉันเพิ่มรายการ ADO.NET Entity Data Model ลงในแอปพลิเคชันคอนโซลของฉันที่ชี้ไปที่Employeeตารางในฐานข้อมูลของฉันและเริ่มเขียนคำสั่ง LINQ
รหัสสำหรับเส้นทาง IQueryable :
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
เมื่อฉันเริ่มรันโปรแกรมนี้ฉันก็เริ่มเซสชันของตัวสร้างโปรไฟล์ SQL Query บนอินสแตนซ์ SQL Server ของฉันและนี่คือบทสรุปของการดำเนินการ:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]มันเป็นสิ่งที่IQueryableฉลาดพอที่จะใช้ส่วนTop (2)คำสั่งบนฝั่งเซิร์ฟเวอร์ฐานข้อมูลของตัวเองดังนั้นมันจึงนำระเบียน 2 จาก 5 เพียงสาย การกรองในหน่วยความจำเพิ่มเติมใด ๆ ไม่จำเป็นต้องใช้กับคอมพิวเตอร์ไคลเอนต์
รหัสสำหรับเส้นทาง IEnumerable :
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
บทสรุปของการดำเนินการในกรณีนี้:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]ตอนนี้สิ่งที่IEnumerableนำระเบียนทั้ง 5 อยู่ในSalaryตารางแล้วทำการกรองในหน่วยความจำบนคอมพิวเตอร์ไคลเอนต์เพื่อรับระเบียน 2 อันดับแรก ดังนั้นข้อมูลเพิ่มเติม (3 บันทึกเพิ่มเติมในกรณีนี้) จึงถูกโอนผ่านสายโดยไม่จำเป็น
นี่คือสิ่งที่ฉันเขียนในโพสต์ที่คล้ายกัน (ในหัวข้อนี้) (และไม่ฉันมักจะไม่พูดเอง แต่บทความเหล่านี้เป็นบทความที่ดีมาก)
"บทความนี้จะเป็นประโยชน์: IQueryable VS IEnumerable ใน LINQ
การอ้างอิงบทความนั้น 'ตามเอกสาร MSDN การเรียกใช้งาน IQueryable จะดำเนินการโดยสร้างแผนผังนิพจน์ภายในแทน "วิธีการเหล่านี้ที่ขยาย IQueryable (Of T) ไม่ทำการสืบค้นใด ๆ โดยตรง แต่หน้าที่การใช้งานของพวกเขาคือการสร้างวัตถุ Expression ซึ่งเป็นทรีนิพจน์ที่แสดงถึงแบบสอบถามแบบสะสม" '
ต้นไม้ Expression เป็นโครงสร้างที่สำคัญมากใน C # และบนแพลตฟอร์ม. NET (สิ่งเหล่านี้มีความสำคัญโดยทั่วไป แต่ C # ทำให้มีประโยชน์มาก) เพื่อให้เข้าใจถึงความแตกต่างได้ดียิ่งขึ้นฉันขอแนะนำให้อ่านเกี่ยวกับความแตกต่างระหว่างนิพจน์และข้อความ ในข้อกำหนด C # 5.0 อย่างเป็นทางการที่นี่ สำหรับแนวคิดทางทฤษฎีขั้นสูงที่แยกเป็นแคลคูลัสแลมบ์ดานิพจน์ช่วยให้การสนับสนุนวิธีการเป็นวัตถุชั้นหนึ่ง ความแตกต่างระหว่าง IQueryable และ IEnumerable นั้นมีศูนย์กลางอยู่ที่จุดนี้ IQueryable สร้าง tree expression ในขณะที่ IEnumerable ไม่ได้อย่างน้อยก็ไม่ได้อยู่ในเงื่อนไขทั่วไปสำหรับพวกเราที่ไม่ทำงานในห้องปฏิบัติการลับของ Microsoft
นี่เป็นอีกบทความที่มีประโยชน์มากที่ให้รายละเอียดความแตกต่างจากมุมมองแบบพุชกับแบบดึง (โดย "push" กับ "pull" ฉันหมายถึงทิศทางของการไหลของข้อมูลเทคนิคการเขียนโปรแกรมแบบโต้ตอบสำหรับ. NET และ C #
นี่เป็นบทความที่ดีมากที่ให้รายละเอียดความแตกต่างระหว่างคำสั่ง lambdas และ lambdas การแสดงออกและกล่าวถึงแนวคิดของการแสดงออกของการแสดงออกในเชิงลึกยิ่งขึ้น: การเยี่ยมชมผู้แทน C #, ต้นไม้แสดงออกและการแสดงออก lambda ."
เราใช้IEnumerableและIQueryableจัดการข้อมูลที่ดึงมาจากฐานข้อมูล IQueryableสืบทอดมาจากIEnumerableดังนั้นจึงIQueryableมีIEnumerableคุณสมบัติทั้งหมด ข้อแตกต่างที่สำคัญระหว่างIQueryableและIEnumerableคือIQueryableเรียกใช้งานแบบสอบถามด้วยตัวกรองในขณะที่IEnumerableเรียกใช้แบบสอบถามก่อนแล้วจึงกรองข้อมูลตามเงื่อนไข
ค้นหาความแตกต่างของรายละเอียดเพิ่มเติมด้านล่าง:
IEnumerable
IEnumerableมีอยู่ในSystem.CollectionsเนมสเปซIEnumerable ดำเนินการแบบสอบถามแบบใช้เลือกข้อมูลในฝั่งเซิร์ฟเวอร์โหลดข้อมูลในหน่วยความจำบนฝั่งไคลเอ็นต์จากนั้นกรองข้อมูลIEnumerable เหมาะสำหรับการสืบค้นข้อมูลจากการรวบรวมในหน่วยความจำเช่น List, ArrayIEnumerable มีประโยชน์สำหรับ LINQ to Object และ LINQ to XML queryIQueryable
IQueryableมีอยู่ในSystem.LinqเนมสเปซIQueryable ดำเนินการ 'เลือกแบบสอบถาม' บนฝั่งเซิร์ฟเวอร์พร้อมตัวกรองทั้งหมดIQueryable เหมาะสำหรับการสืบค้นข้อมูลจากหน่วยความจำนอก (เช่นฐานข้อมูลระยะไกลบริการ)IQueryable มีประโยชน์สำหรับ LINQ กับการสืบค้น SQLดังนั้นIEnumerableโดยทั่วไปจะใช้สำหรับจัดการกับการรวบรวมในหน่วยความจำในขณะที่IQueryableโดยทั่วไปจะใช้เพื่อจัดการกับคอลเลกชัน
ทั้ง IEnumerable และ IQueryable นั้นใช้สำหรับเก็บข้อมูลและทำการดำเนินการจัดการข้อมูลเช่นการกรองในการรวบรวมข้อมูล ที่นี่คุณสามารถค้นหาความแตกต่างที่ดีที่สุดพร้อมตัวอย่าง
http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html

IQueryable เร็วกว่า IEnumerable ถ้าเราจัดการกับข้อมูลจำนวนมากจากฐานข้อมูลเพราะ IQueryable จะได้รับเฉพาะข้อมูลที่ต้องการจากฐานข้อมูลที่ IEnumerable ได้รับข้อมูลทั้งหมดโดยไม่คำนึงถึงความจำเป็นจากฐานข้อมูล
ienumerable: เมื่อเราต้องการจัดการกับหน่วยความจำ inprocess เช่นไม่มี dataconnection iqueryable: เมื่อต้องจัดการกับ sql server, เช่นการเชื่อมต่อ data ilist: การดำเนินการเพิ่มวัตถุลบวัตถุ ฯลฯ