ฉันสังเกตเห็นปัญหาหลายประการในคำตอบของ @ gunny229 ด้านบน ซึ่งเป็นสาเหตุที่ฉันเขียนโพสต์นี้ ฉันได้กล่าวถึงปัญหาเหล่านั้นในพื้นที่แสดงความคิดเห็นของโพสต์ของเขาแล้วเช่นกัน เพื่อแก้ไขโพสต์นั้น ฉันจะต้องเขียนใหม่เกือบทั้งโพสต์ ดังนั้นฉันจึงคิดที่จะสร้างโพสต์ของตัวเองขึ้นมา ฉันไม่ได้ตั้งใจที่จะตอบคำถามของ OP ทั้งหมด แต่ฉันต้องการชี้ให้เห็น ความแตกต่างระหว่าง IQueryable และ IEnumerable เมื่อใช้ LINQ กับ SQL
ฉันสร้างโครงสร้างต่อไปนี้ใน 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 ของฉันด้วย และนี่คือบทสรุปของการดำเนินการ:
- จำนวนคำค้นหาทั้งหมดที่ถูกเรียกใช้: 1
- ข้อความค้นหา:
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);
}
}
สรุปการดำเนินการในกรณีนี้:
- จำนวนคำค้นหาทั้งหมดที่ถูกเรียกใช้: 1
- ข้อความค้นหาที่บันทึกในตัวสร้างโปรไฟล์ SQL:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
ตอนนี้สิ่งที่ IEnumerable
นำระเบียนทั้งหมด 5 รายการที่มีอยู่ในตาราง Salary
จากนั้นดำเนินการกรองในหน่วยความจำบนคอมพิวเตอร์ไคลเอนต์เพื่อให้ได้ 2 ระเบียนสูงสุด ดังนั้นข้อมูลเพิ่มเติม (บันทึกเพิ่มเติม 3 รายการในกรณีนี้) จึงถูกถ่ายโอนผ่านทางสายโดยไม่จำเป็น
person
RBT
schedule
26.04.2017