ورود به حساب کاربری        عضویت
مشاوره تلفنی    05136615381 - 09155249646 - 05136639567  

09
آوریل

۰

آشنایی با تکنولوژی LINQ در C#

شاید اولین سوالی که در ذهن هر یک از شما پیش بیاد این باشه که چه تعریفی می توان برای LINQ ارائه داد؟ چه کارهایی می توان با LINQ انجام داد؟ LINQ چه قابلیت هایی را در اختیار یک برنامه نویس قرار می دهد؟ به این سوالات می شود به این صورت جواب داد که LINQ شامل یکسری عملگرهای استاندارد است که به شما امکان می دهد بر روی انواع منابع داده در داخل زبان های سازگار با NET. مانند VB.NET یا #C کوئری هایی را نوشته و اجرا کنید. نام Language Integrated Query  نیز به این دلیل انتخاب شده است که این کوئری ها داخل یک زبان برنامه نویسی مانند #C نوشته و اجرا می شوند. اما منابع داده ای که LINQ می تواند از آنها استفاده کند می تواند یک شئ ایجاد شده، یک فایل مستندات XML، یک بانک SQL Server و یا یک منبع دلخواه باش LINQ .این قابلیت را دارد که با تمامی این منابع داده کار کند. علاوه بر استخراج و اجرای کوئری بر روی منابع داده نیز، بوسیله LINQ شما امکان تغییر و دستکاری یک منبع داده مانند یک بانک SQL Server را خواهید داشت.

 

انواع LINQ :

Linq to Object

Lint to XML

Linq to ADO.Net

Linq to Array

Linq to SQL

Linq to Entity Framework

 

هدف

از اهداف Linq می توان به این مورد اشاره کرد که وقتی ما درستورات SQL رو در خود SQL Server Management می نویسیم اونجا توانایی خطا یابی وجود دارد. همون طور که در فیلم چهارم (آموزش SQL در ساخت پروژه ی فروشگاهی با Asp.net MVC) این مورد به وفور یافت می شود. ولی زمانی که ما همین دستورات SQL رو در خود Visual Studio می نویسیم اون جا چون این دستورات از اجزا و ساختار های شناخته شده در C# محصوب نمی شوند لازم است که به صورت رشته از آن ها استفاده نماییم برای مثال:

“SELECT * FROM Tbl_Mobiles”

دستور بالا را در SQL Server اگر بنویسیم می توانیم به صورت بالا ازش استفاده نماییم. ولی اگر در C# بخوایم بنویسیم(البته در ADO.Net) باید آن را داخل “” و در قسمت تعیین شده قرار دهیم.

حالا کدهای بالا که داخل “” قرار دارند تا زمان اجرا نمی توان از خطاهای آن مطلع شد. پس یکی از اهداف Linq همین مورد است که ما زمانی که دستورات را به صورت Linq  حالا Lambda expressions یا Query Expression می نویسیم خودش میاد و به دستورات SQL تبدیل میشه و در مرحله ی بعد دستورات Sql تزریق میشه و نتایج برگردونده میشن.

البته اهداف دیگری هم دارند مثلا عملیات جستوجو حالا در بانک یا در یک ارایه از داده ها خیلی آسونتر می کنند.

وقتی که به مسائل عملی برسیم این موارد رو مثال می زنیم.

 

معرفی Lambda expressions و Query Expressions

 

Query Expression

خوب، تو اولین مرحله می خواییم با ساختار و اجزای تشکیل دهنده یک کوئری آشنا بشیم. اگه بخواییم ساختار کلی یک کوئری LINQ رو نمایش بدیم، ساختار یک کوئری LINQ به صورت زیر می باشد
 

 

from <element> in <data_source>

[query standard operators]

select <element type in returned sequence>


همانطور که در بالا مشاهده میکنید کوئری های LINQ از بخش های مختلفی تشکیل شده اند. (قسمت هایی که داخل <> قرار گرفته توسط کاربر تعیین شده و اجباری می باشند و قسمت هایی که داخل [] قرار گرفته اند اختیاری می باشند، باقی اجزاء که داخل نشانه ای قرار نگرفته اند بخش های پیش فرض کوئری های LINQ هستند) 

 

From :

تمامی کوئری های LINQ با کلمه کلیدی from آغاز می شوند. این کلمه نشان دهنده آغاز یک کوئری LINQ است.


 

<Element>:

 این قسمت نمایش دهنده یکی از عناصر موجود در data source ایست که می خواهیم از آن کوئری بگیریم. انتخاب نام برای این قسمت آزاد است و می توان هر نامی را برای آن انتخاب کرد. برای مثال اگر لیستی داشته باشیم که عناصر موجود در آن از نوع int باشند، زمان اجرای کوئری element از نوع int در نظر گرفته خواهد شد.

 


 

In:

بخش بعدی یک کوئری LINQ کلمه کلیدی in است و نوشتن آن در تمام کوئری های LINQ اجباریست، بوسیله این کلمه که قبل از نام data_source می آید، تعیین می کنیم که کوئری بر روی کدام منبع داده باید اجرا شود.


 

<data_source>:

 در این بخش نام منبع داده ای که می خواهیم کوئری بر روی آن اجرا شود را می نویسیم.


 

<Query standard operators>  :

این بخش حاوی تمامی operator های استاندارد LINQ است که برای عملیات فیل تر کردن اطلاعات، مرتب سازی، گروه بندی و یا ادغام از آنها استفاده می شوند. درباره اپراتور های استاندارد LINQ در بخش بعدی صحبت خواهیم کرد.


 

Select:

 این کلمه کلیدی بعد از بخش اپراتور های استاندارد می آید و نوشتن آن در تمام کوئری های LINQ اجباری است. این کلمه نشان دهنده به پایان رسیدن یک کوئری LINQ است و وظیفه انتخاب عناصر مورد نظر از منبع داده را دارد.


 

: < Element type in returned sequence>

 این قسمت نوع عناصر موجود در لیست ایجاد شده توسط کوئری را تعیین میکند، می توان نوع خروجی های کوئری را به طور دلخواه تعیین کرد.


برای درک بهتر هر یک از بخش های بالا با یک مثال جلو میریم


 

int[] nums = { 4, 1, 7, 5, 9, 6, 2 };

 

var query = from n in nums

                  where n > 4

                  select n;

 

foreach (int s in query)

    Console. Write(s);


همانطور که گفته شد، کوئری با کلمه کلیدی from آغاز می شو، n در کوئری بالا نشان دهنده یکی از عناصر موجود در منبع داده است که از آن برای عملیات های فیل تر کردن استفاده می کنیم، بعد از n، کلمه کلیدی in و بعد از آن منبع داده مورد نظر است که در این کوئری منبع داده مورد نظر ما آرایه nums است. در بخش بعدی از اپراتور استاندارد where که برای فیل تر کردن اطلاعات استفاده می شود، استفاده کردیم، برای فیل تر سازی اطلاعات، از n که در خط اول کوئری تعریف کردیم استفاده کردیم، در خط بعدی هم بعد از کلمه کلیدی select نوع عناصر موجود در query را تعیین می کنیم. در اینجا با استفاده از متد ToString تعیین کردیم که عناصر موجود در کوئری از نوع string باشند. اگر به جای n.ToString()، تنها n را می نوشتیم، عناصر موجود در لیست برگردانده شده توسط کوئری از نوع int در نظر گرفته می شد

 

 

استفاده از متدهای کوئری و Lambda Expressions


در مورد روش اول در بخش های قبلی صحبت کردیم. در روش دوم از Extension Method هایی استفاده می کنیم که در net. نسخه ۳٫۵ اضافه شده اند. استفاده از این Method ها برای نوشتن کوئری انعطاف پذیری بیشتری رو در نوشتن کوئری ها به ما میدن. نوشتن کوئری بالا با استفاده از متد های کوئری به صورت زیر است
 

int[] nums = { 4, 1, 7, 5, 9, 6, 2 };

var query = nums.Where(n => n > 4).Select(n => n);

 

foreach (int s in query)

    Console.WriteLine(s);


اما گفتیم که استفاده از متد ها در نوشتن کوئری انعطاف پذیری بیشتری دارند. یک نمونه از این انعطاف پذیری انتخاب ایندکس های دلخواه در کوئری گرفته شده است. برای مثال فرض کنیم بخواهیم در کوئری گرفته شده، فقط ایندکس های زوج را برگردانیم
 

 

int[] nums = { 4, 1, 7, 5, 9, 6, 2 };

var query = nums.Where((n,index) => n > 4 && index % 2 == 0).Select(n => n.ToString());

 

foreach (string s in query)

    Console.Write(s);


پارامتر دومی که داخل متد where با نام index تعریف شده، نشان دهنده ایندکس مربوط به هر یک از عناصر نتیجه برگردانده شده از شرط قبل از شر index است. در ایجاد تمامی ایندکس های زوج برگردانده می شوند. متدهایی که در نوشتن کوئری استفاده می شوند پارامتر های ورودی دیگری نیز دارند که برای آشنایی با آنها می توانید از MSDN استفاده کنید. در بخش های بعدی مقاله با استفاده از این متدها بیشتر آشنا خواهیم شد

اما امکان بعدی که در مورد آن می خواهیم بحث کنیم قابلیت استفاده از Anonymous Types در نوشتن کوئری ها است. همانطور که در بخش قبلی گفتیم Anonymous Types نوع هایی بی نام هستند که می توانند دارای یکیسری خصوصیات باشند. در کوئری های LINQ میتوانیم تعیین کنیم که خروجی ما از نوع Anonymous Types باشند. به مثال زیر توجه کنید، می خواهیم خروجی کوئری نوعی که تنها حاوی خصوصیت FullName است باشد، FullName از ترکیب خصوصیات FirstName و LastName در شئ Person تشکیل شده است (در کد زیر از کلاس Person که در بخش اول ایجاد کردیم استفاده می کنیم) :
 

List<Person> persons = new List<Person>()

{

    new Person() { FirstName = “Ali”, LastName = “Jamali”, Age = 42 },

    new Person() { FirstName = “Hosein”, LastName = “Ahmadi”, Age = 23 },

    new Person() { FirstName = “Mohamamd”, LastName = “Sadeghi”, Age = 17 },

    new Person() { FirstName = “Reza”, LastName = “Ahmadi”, Age = 24 },

    new Person() { FirstName = “Nima”, LastName = “Karami”, Age = 18 }

};

 

var query = from p in persons

                 where p.Age > 20

                 select new { FullName = p.FirstName + ” ” + p.LastName };

 

foreach (var at in query)

{

    Console.WriteLine(at.FullName);

}


نوشتن کوئری بالا با استفاده از متدهای کوئری نیز امکان پذیر است
 

 

var query = persons.Where(p => p.Age > 20)

                             .Select(n => new { FullName = n.FirstName + ” ” + n.LastName });


اما نحوه اجرای کوئری ها در LINQ به چه صورت است. وقتی شما داخل کد برنامه ای که نوشتید از کوئری LINQ استفاده کردید، هنگام اجرا، وقتی برنامه به کوئری LINQ می رسد، در اصل کوئری اجرا نمی شود، بلکه هنگامی کوئری اجرا می شود که از نتایج کوئری استفاده شود. در مثال های بالا کوئری های نوشته شده زمانی اجرا می شوند که برنامه به دستور foreach می رسد. به همین دلیل به اجرای کوئری های LINQ در زبان انگلیسی Deferred-Query-Execution یا اجرای کوئری با تاخیر نیز می گویند. البته می توان کوئری ها را در همان خطی که کوئری نوشته شده است اجرا کرد. این کار به استفاده از متد های ToList، ToArray، ToDictionary و ToLookup امکان پذیر است. این متد ها نتیجه کوئری را به یکی از مجموعه های List، Array، Dictionary و یا LookUp تبدیل می کنند. برای درک بهتر به مثال زیر دقت کنید
 

List<Person> query = persons.Where(p => p.Age > 20).ToList();

 

foreach (var p in query)

{

    Console.WriteLine(p.ToString());

}


اگر بخواهیم کوئری بالا را با استفاده از دستورات LINQ بنویسیم باید به صورت زیر عمل کنیم
 

List<Person> query = (from p in persons

                                 where p.Age > 20

                                 select p).ToList();


همانطور که مشاهده میکنید در کوئری بالا، بلافاصله نتیجه کوئری با استفاده از متد ToList داخل یک مجموعه List ریخته می شود و سپس با دستور foreach این لیست مورد پیمایش قرار می گیرد. دستور ToDictionary برای ایجاد یک Dictionary که حاوی یک کلید است استفاده می شود
 

Dictionary<string, Person> query = persons.Where(p => p.Age > 20).ToDictionary(n => n.FirstName);

Console.WriteLine(query[“Hosein”].ToString());


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

 

 

 

 

مزایا و معایب LINQ

 

مزایای استفاده از Linq چیست ؟

 

ارائه یک ساختار (زبان پرس و جو) برای پرس و جو کردن اطلاعاتی از قبیل پایگاه داده ها ، XML ها ، ADO.NET Dataset ، وب سرویس ها و سایر اشیا مانند آرایه ها و لیست ها

کنترل نوع (type checking) کامل که در Linq می باشد همراه با IntelliSense کمک می کند تا خطاهای زمان اجرا به شدت کاهش بیابند

ارائه توابع مانند filtering ، مرتب سازی و grouping با حداقل کدنویسی

امکان استفاده مجدد از جست و جوی ایجاد شده

امکان دیباگ کردن با دیباگر .NET

 

معایب Linq چیست ؟

 

Linq  برای نوشتن جست و جوهای پیچیده گزینه مناسبی نیست

عدم ارائه تمامی توانایی های SQL ، مانند کش کردن execution plan ها در stored procedure

در صورتی که شما جست و جوی اصولی ننوشته باشید Performance پائین تری خواهید داشت.

اگر قصد ویرایش در جست و جو را داشته باشید باید برنامه را از نو کامپایل کرده و به سرور منتقل نمایید.

 

بدون دیدگاه

پاسخ