مشخصات مقاله
-
1326
-
0.0
-
3129
-
0
-
0
مقایسه Query Syntax با Method Syntax
کلیه حقوق مادی و معنوی این مقاله متعلق به آموزشگاه تحلیل داده می باشد و هر گونه استفاده غیر قانونی از آن پیگرد قانونی دارد.
Query Syntax (نوشتن به روش کوئری) در مقایسه با Method Syntax (تنظیم کوئری به روش متد) در LINQ
اغلب کوئری ها یا دستورات پرس وجویی که در مستندات مقدماتی آموزش LINQ بکار برده می شوند به روش Query syntax نوشته و تنظیم می گردند. Query syntax بایستی (زمان کامپایل توسط مترجم) به method syntax (نوشتن به صورت متد) تبدیل شود. method syntax که به صورت تابع فراخوانی می شود، عملگرهای متعارف SQL نظیر where، select، GroupBy، join، Max و Average را بکار می اندازند (صدا می زنند).
می توانید بجای استفاده از روش query syntax، عملگرهای ذکر شده را با تنظیم کوئری به روش متد (method syntax) مستقیما فراخوانی نمایید. از نظر کارایی method syntax و query syntax مشابه هستند، با این حال بیشتر برنامه نویسان روش نوشتن به صورت کوئری را به دلیل سادگی و قابلیت خوانایی بیشتر، به method syntax ترجیح می دهند. برخی از کوئری ها بایستی به روش متد (method syntax) نوشته شوند. به عنوان مثال، برای نوشتن کوئری که تعداد المان های منطبق با شرط را برمی گرداند، بایستی آن (کوئری) را به روش method syntax نوشت. همچنین برای نوشتن کوئری که المان با بزرگترین مقدار را از منبع داده بازیابی کند نیز از method syntax استفاده می کنیم. معمولا در مستند سازی فضای نام system.linq از method syntax برای توصیف عملگرهای متعارف SQL استفاده می شود. بنابراین حتی زمانی که شروع به استفاده و نوشتن کوئری های LINQ می کنید، بد نیست با نحوه ی استفاده از کوئری به روش method syntax در query ها یا خود عبارت queryها آشنا باشید.
Extension method ها (متدهای پسوندی و الحاقی) در عبارت های Query
مثال زیر دستور یک کوئری ساده را نشان می دهد که به دو روش query syntax و method syntax نوشته شده است.
class QueryVMethodSyntax
{
static void Main()
{
int[] numbers = { 5, 10, 8, 3, 6, 12};
//Query syntax:
IEnumerable<int>numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
//Method syntax:
IEnumerable<int>numQuery2 = numbers.Where(num =>num % 2 == 0).OrderBy(n =>n);
foreach (int i in numQuery1)
{
Console.Write(i + " ");
}
Console.WriteLine(System.Environment.NewLine);
foreach (int i in numQuery2)
{
Console.Write(i + " ");
}
// Keep the console open in debug mode.
Console.WriteLine(System.Environment.NewLine);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
خروجی که از اجرای دو کوئری فوق بدست می آید، یکسان است. همان طور که مشاهده می کنید متغیری که دستور کوئری را در خود ذخیره می کند در هر دو نمونه یکسان است: IEnumerable<T> .
برای فهم نمونه ی دوم (تنظیم کوئری با ساختار متد)، می بایست آن را دقیق تر بررسی کنیم. در سمت راست عبارت (دستور) کوئری، همان طور که مشاهده می کنید، عملگر where اکنون به صورت یک متد به شی number الحاق شده است. اگر بخاطر داشته باشید، نوع این شی IEnumerable<T> می باشد. در صورتی که با اینترفیس جنریک IEnumerable<T> آشنا باشید، قطعا می دانید که این اینترفیس هیچ متدی به نام where ندارد. اما چنانچه لیست تکمیلی این اینترفیس را با فراخوانی امکان Intellisense محیط برنامه نویسی ویژوال استودیو باز کنید، می بینید که نه تنها دارای یک متد where هست بلکه متدهای دیگری نظیر Select، SelectMany، Join و Orderby را نیز شامل می شود. تمامی این متدها در واقع عملگرهای متعارف SQL می باشند.
ممکن است چنین بنظر برسد که رابط IEnumerable<T> مورد ویرایش قرار گرفته و این متدهای پسوندی به آن اضافه شده اند، اما چنین نیست. عملگرهای معمولی SQL همچون Where، Select در قالب یک متد جدید به نام extension method پیاده سازی می شوند. متدهای الحاقی (extension method) به انتهای شی که از نوع خاصی است پوست می شوند آن شی (متغیر) را به عنوان آرگومان پذیرفته و عملیاتی را بر روی آن انجام می دهد و نتیجه را برمی گردانند. Extension method ها را می توان به صورت زیر نوشت:
numbers.Where(...)
برای شورع به استفاده از دستورات LINQ، تمام آنچه باید درباره ی Extension method ها بدانید این است که آن ها را چگونه با استفاده از دستور using وارد حوزه ی برنامه ی جاری خود کرده و مورد استفاده قرار دهید.
عبارت های lambda
اگر بار دیگر به مثال قبلی نگاهی بایندازید، متوجه می شوید که عبارت شرطی (num % 2 == 0) به عنوان پارامتر به صورت درون خطی (inline) به متد where پاس داده شده است: Where(num =>num % 2 == 0). این عبارت دورن خطی که به صورت آرگومان درون خطی به متد الحاقی (extension method) ارسال می گردد و فیلتر را اعمال می کند، در اصطلاح عبارت lambda خوانده می شود. بدین وسیله می توان کدی را که در غیر این صورت می بایست با کدنویسی اضافی همچون نوشتن متدهای فاقد اسم (anonymous method) یا delegate جنریک و یا expression tree (کدهایی با ساختار درختی) می نوشتید، به راحتی و با نوشتن یک خط کد خاتمه دهید. در زبان C# علامت => در واقع یک عملگر lambda به معنی "نتیجه می دهد" است. num ای که در سمت چپ عملگر قرار می گیرد، متغیر ورودی و متناظر با متغیر num در دستور کوئری می باشد. منبع داده متغیری با نام numbers از نوع اینترفیس جنریک IEnumerable<T> می باشد، و از آنجایی که کامپایلر بر حقیقت اشراف دارد، می تواند خود نوع داده ای متغیر ورودی num را تشخیص دهد. بدنه ی عبارت lambda، درست مشابه دستور کوئری در query syntax (روش نوشتن با ساختار کوئری) یا هر عبارت و دستور دیگری در C# است؛ بدین معنی که قادر است extension method یا هر منطق پیچیده ی دیگری را شامل شود. مقدار بازگشتی، نتیجه اجرای عبارت یا همان خروجی دستور کوئری می باشد.
بخش های تشکیل دهنده ی Query
در نمونه کد قبلی متد OrederBy با استفاده از عملگر نقطه (پس از عبارت lambda) به متد Where متصل شده و فراخوانی گردیده است. متد where یک دنباله ی فیلتر شده برمی گرداند (نتایجی را که با شرط مشخص شده در عبارت لامبدا منطبق هستند را به صورت دنباله برمی گرداند) و سپس متد OrderBy صدا زده شده و بر روی نتیجه ی متد اول عملیات مرتب سازی را انجام می دهد (نتیجه را بر اساس ترتیب عددی مرتب می کند). از آنجایی که کوئری ها یک IEnumerable برمی گردانند، آن ها را با ساختار نگارشی متد (method syntax) نوشته و در آن متدها را به صورت زنجیره ای و دنباله ای به هم متصل کرده و فراخوانی می کنیم. این دقیقا همان کاری است که زمانی که کوئری را با ساختار نگارشی method syntax می نویسیم کامپایلر در پشت صحنه انجام می دهد. بدین معنی که کامپایلر در زمان ترجمه و اجرای کد، آن را از query syntax به method syntax تبدیل می کند. به این خاطر که متغیر ذخیره کننده ی دستور کوئری (query variable) نتایج آن را ذخیره نمی کند، می توانید نتیجه ی کوئری را ویرایش نموده و به عنوان پایه و مبنا برای کوئری دیگر بکار ببرید.