عملگرهای تبدیل در LINQ
چهارشنبه 3 تیر 1394در این مقاله به نحوه آموزش عملگرهای تبدیل در LINQ میپردازیم که این دسته از عملگرها برای تبدیل مجموعه ورودی به انواع دیگر مورد استفاده قرار میگیرد.
عملگرهای تبدیل در LINQ شامل زیر می باشد :
ToList. 1
ToArray. 2
ToDictionary. 3
ToLookup. 4
Cast. 5
OfType. 6
AsEnumerable. 7
اما قبل از پرداختن به جزئیات بیشتر ما باید هردیرکرد(با تاخیر) و اجرای مستقیم(آنی) را یاد بگیریم که اجرای با تاخیر و اجرای آنی چیست؟ عملگرهای LINQ میتواند به دسته بندی های زیر تقسیم شود :
دیرکرد یا کندبودن عملگرها : به عنوان مثال Select، Where، Take، Skip و ..
عملگرهای مستقیم : به عنوان مثال Count، Max ، Min ، Average، ToList و ...
یک مثال از اجرای دیرکرد را در زیر مشاهده کنید :
using System; using System.Collections.Generic; using System.Linq; namespace DeferredAndImmediate { class Employee { public int Id{get;set;} public string Name {get;set;} public double Salary{get;set;} } class Program { static void Main(string[] args) { List < Employee > EmployeeList = new List < Employee > () { new Employee() { Id = 1, Name = "Sam", Salary = 41000 }, new Employee() { Id = 2, Name = "Max", Salary = 41000 }, new Employee() { Id = 3, Name = "Sara", Salary = 21000 } }; } } }
در پروژه یک کلاس به اسم Employee با سه خصوصیت داریم.
در متد اصلی لیستی از employees (کارکنان) وجود دارد.
حالا ما میخواهیم تمام employee هایی که salary=41000 است را ذخیره کنیم.
IEnumerable<Employee> employees = from employee in EmployeeList where employee.Salary == 41000 select employee;
از میان هر employee ما می توانیم از حلقه foreach استفاده کنیم .
foreach(Employee emp in employees) { Console.WriteLine(emp.Name); }
قبل از شروع این برنامه باید بدانیم که این برنامه دقیقا در کجا اجرا می شود و چیزی که سعی داریم به این موضوع اشاره کنیم این است که، برنامه در این قسمت اجرا می شود.
IEnumerable<Employee> employees = from employee in EmployeeList where employee.Salary == 41000 select employee; Or during the foreach loop. foreach(Employee emp in employees) { Console.WriteLine(emp.Name); }
این برنامه در واقع در حین حلقه foreach اجرا می شود و اثبات میکند که ما می توانیم یک item employee به لیست اضافه کنیم.
برنامه را اجرا کنید.
در خروجی ما سه رکورد بدست می آوریم که به این معناست ، Query قبلی ما در حین حلقه ی foreach اجرا شده و به این اشاره می کند که این یک برنامه ی کند اجرا است .
حالا به عنوان یک مثال اجرای آنی (مستقیم) را در زیر مشاهده کنید :
IEnumerable<Employee> employees = (from employee in EmployeeList where employee.Salary== 41000 select employee).ToList(); Convert the above linq query to a list. EmployeeList.Add(new Employee() { Id = 4, Name = "Aiden", Salary = 41000 }); foreach(Employee emp in employees) { Console.WriteLine(emp.Name); }
برنامه را اجرا کنید :
در اینجا ما دوتا رکورد داریم که به این معناست که ToList یک عملگر اجرایی آنی می باشد.همانند Count,max,min که عملگرهای اجرای مستقیم (آنی) هستند. بنابراین ما کمی درک اساسی از دیرکرد و اجرای مستقیم داریم .
ToList :
عملگرهای Tolist یک item را از یک لیست مرتب خارج میکند و یک لیست جدید را برمیگرداند و این عملگرها را برای اجرای مستقیم استفاده می کنند.
static void Main(string[] args) {#region ToList //create array of integers int[] numbers = { 1, 2, 3, 4, 5 }; //convert array to list which will return list of integers List < int > listNumber = numbers.ToList(); //loop thru each list item foreach(int item in listNumber) { Console.WriteLine(item); }#endregion }
برنامه را اجرا کنید .
ToArray :
این عملگر، item ها را از یک رشته استخراج می کند و یک آرایه جدید را بر می گرداند ، که این عملگر باعث اجرای مستقیم میشود.
#region ToArray //create a list of string List < string > BrandList = new List < string > () { "Apple", "Microsoft", "Google", "Samsung", "Sony" }; //retrieve items from the list in ascending order and convert them to array string[] brandArray = (from brand in BrandList orderby brand ascending select brand).ToArray(); foreach(string item in brandArray) { Console.WriteLine(item); }#endregion
ToDictionary :
این عملگر Query را اجرا می کند که تمام item ها را به عنوان یک رشته دریافت کرده و یک مقادیر dictionary را بر می گرداند.
این یک عملگر اجرای آنی می باشد.
class Employee { public int Id {get;set;} public string Name {get;set;} public double Salary {get;set;} } class Program { static void Main(string[] args) {#region ToDictionary List < Employee > employeeList = new List < Employee > () { new Employee() { Id = 1, Name = "Sara", Salary = 41000 }, new Employee() { Id = 2, Name = "Sam", Salary = 11000 }, new Employee() { Id = 3, Name = "Aiden", Salary = 21000 } }; Dictionary < int, Employee > employeeDic = employeeList.ToDictionary(x = > x.Id, y = > y); foreach(KeyValuePair < int, Employee > employee in employeeDic) { Console.WriteLine(employee.Key); Console.WriteLine(employee.Value.Name); }#endregion } }
برنامه را اجرا کنید.
ToLookup :
همانند یک dictionary ، یک Lookup مجموعه ای از کلید و مقادیر می باشد. تنها تفاوت بین این دو در این هست که یک dictionary نمی تواند شامل کلیدهایی با مقادیر یکسان باشد در حالی که یک lookup می تواند.
class Employee { public string Name {get;set;} public string JobTitle {get;set;} public string City {get;set;} } static void Main(string[] args) {#region ToLookup //create a list of employees List < Employee > employeeList = new List < Employee > () { new Employee() { Name = "Aiden", JobTitle = "Sr. Developer", City = "London" }, new Employee() { Name = "Max", JobTitle = "Developer", City = "Bangalore" }, new Employee() { Name = "Sara", JobTitle = "Developer", City = "Bangalore" }, new Employee() { Name = "Lara", JobTitle = "Sr. Developer", City = "London" }, new Employee() { Name = "Michael", JobTitle = "Developer", City = "London" }, new Employee() { Name = "Sam", JobTitle = "Developer", City = "London" } }; //pass JobTitle as a key in the ToLookup method ILookup < string, Employee > employeeLookup = employeeList.ToLookup(x = > x.JobTitle); Console.WriteLine("Employee grouped by JobTitle"); Console.WriteLine(); //loop thru each items in employeelookup which will give IGrouping of key and value foreach(IGrouping < string, Employee > kvp in employeeLookup) { //print the key Console.WriteLine(kvp.Key); //add another foreach loop, using the key look for the items. This will return employee object back foreach(Employee emp in employeeLookup[kvp.Key]) { Console.WriteLine("\t" + emp.Name + "\t" + emp.City); } Console.WriteLine(); }#endregion } }
برنامه را اجرا کنید.
ما می توانیم حتی آن ها را بر حسب city دسته بندی کنیم .
ILookup < string, Employee > employeeLookup = employeeList.ToLookup(x = > x.City); Console.WriteLine("Employee grouped by JobTitle"); Console.WriteLine(); foreach(IGrouping < string, Employee > kvp in employeeLookup) { Console.WriteLine(kvp.Key); foreach(Employee emp in employeeLookup[kvp.Key]) { Console.WriteLine("\t" + emp.Name + "\t" + emp.JobTitle); } Console.WriteLine(); }
برنامه را اجرا کنید.
Cast :
عملگر Cast تلاش دارد تا تمام item ها را به یک نوع دیگر تبدیل کند و آن ها را به یک مجموعه جدید برگرداند. وقتی که در یک item عملگر تبدیل انجام نشد یک درخواست ارسال می شود. متد Cast یا عملگر از اجرای دیر کرد استفاده می کند.
ArrayList al = new ArrayList(); al.Add(2); al.Add(4); al.Add(6); al.Add(8); IEnumerable<int> numbers = al.Cast<int>(); foreach(int item in numbers) { Console.WriteLine(item); }
در نمونه کد قبلی ما یک arraylist را ساختیم و این arraylist یک item را برمیگرداند سپس توسط عملگر cast مقادیر arraylist را به integer تبدیل می کند.
برنامه را اجرا کنید.
یک item جدیدی را به همان arraylist قبلی، طبق مثال زیر اضافه می کنیم :
;("9")al.Add
برنامه را اجرا کنید.
4عدد اول چاپ شدنداما پنجمین عدد یک استثنا وجود دارد هنگامی که پنجمین item از نوع رشته می باشد. و عملگر cast قادر نبود تا آن را به نوع integer تبدیل کند. پس ما همیشه استفاده می کنیم از عملگر cast ،که یک مجموعه item از نوع داده تعیین شده را بر می گرداند.
ofType :
عملگر ofType فقط item های تایید شده را بر می گرداند و بقیه itemها در خروجی نمایش داده نمی شود. این ofType از اجرای دیرکرد استفاده می کند.
ArrayList al = new ArrayList(); al.Add(2); al.Add(4); al.Add(6); al.Add(8); al.Add("9"); IEnumerable<int> numbers = al.OfType<int>(); foreach(int item in numbers) { Console.WriteLine(item); }
در نمونه کد قبلی ما یک arraylist داشتیم که شامل 4 item integer و یک item string بود.
برنامه را اجرا کنید .
ما فقط مقدار integer را دریافت کردیم زیرا این عملگر ofType همیشه فقط item های نوع داده تعیین شده را بر می گرداند.
AsEnumerable :
از این عملگر بر ای انتقال Query های در حال اجرا به سمت کاربر استفاده کنید . این عملگر Query را به دو قسمت زیر تقسیم می کند :
1. اول قسمت داخلی است به عبارت دیگر قبل از AsEnumerable اجرا می شود با استفاده از تبدیل LINQ به SQL
2. دوم قسمت خارجی است به عبارت دیگر بعد از AsEnumerable اجرا می شود با استفاده از تبدیل LINQ به object
به این مثال توجه کنید :
ما برای نمونه از جدول زیر استفاده کردیم .
Query برای این جدول :
CREATE DATABASE db_AsQueryable GO USE db_AsQueryable Create Table Employees ( ID int primary key identity, Name nvarchar(50), Gender nvarchar(50), Salary int ) GO Insert into Employees Values('Mark','Male','60000') Insert into Employees Values('Steve','Male','45000') Insert into Employees Values('Ben','Male','70000') Insert into Employees Values('Philip','Male','45000') Insert into Employees Values('Mary','Female','30000') Insert into Employees Values('Valarie','Female','35000') Insert into Employees Values('John','Male','80000') Insert into Employees Values('Pam','Female','85000') Insert into Employees Values('Stacey','Female','65000') Insert into Employees Values('Andy','Male','73000') Insert into Employees Values('Edward','Male','65000') GO
اضافه کردن LINQ به SQL data model :
در قسمت server explorer از view و بروی connect to a database کلیک کنید و نام سرور و بانک اطلاعاتی را تعیین کنید .
جدول Emploees را بکشید به پنجره designer و رها کنید .
در متد اصلی پروژه همانند شکل زیر اضافه کنید :
EmployeeDBDataContext employee = new EmployeeDBDataContext(); var emp = employee.Employees.Where(x => x.Gender == "Male").OrderByDescending(x => x.Salary).Take(5); foreach(var item in emp) { Console.WriteLine(item.Name + "\t" + item.Gender + "\t" + item.Salary); }
سپس SQL Server profiler را باز کنید و console application را اجرا کنید.
در SQl Server Profiler به کدهایی نگاه کنید که ایجاد شدند تا اجرا شوند و نتایج را به ما بدهند.
بعد از خصوصیت employees و قبل از آن جایی که عملگر AsEnumerable فراخوانی می شود برنامه را بر می گرداند.
var emp = employee.Employees.AsEnumerable().Where(x => x.Gender == "Male").OrderByDescending(x => x.Salary).Take(5);
در واقع خروجی هیچ تغییری نمی کند .
در Sql Server Profiler کدهایی که ایجاد شده است را مشاهده کنید.
- C#.net
- 2k بازدید
- 1 تشکر