عملگرهای تبدیل در LINQ

چهارشنبه 3 تیر 1394

در این مقاله به نحوه آموزش عملگرهای تبدیل در LINQ میپردازیم که این دسته از عملگرها برای تبدیل مجموعه ورودی به انواع دیگر مورد استفاده قرار میگیرد.

عملگرهای تبدیل در 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  کدهایی که ایجاد شده است را مشاهده کنید.

 

فایل های ضمیمه

نرگس محمدی

نویسنده 36 مقاله در برنامه نویسان
  • C#.net
  • 2k بازدید
  • 1 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید