اجرای کوئری با تاخیر
اجرای با تاخیر (Deferred Execution) به این معنا است که ارزیابی یک عبارت تا زمانی که مقدار واقعی آن مورد نیاز باشد به تأخیر می افتد. با استفاده از این روش می توان کارایی را تا حد زیادی بهبود بخشید.
اجرای با تاخیر در همه مجموعه های in-memory و زیر مجموعه های LINQ مانند LINQ-to-SQL، LINQ-to-Entities، LINQ-to-XML و غیره قابل اعمال است. برای درک بهتر به مثال زیر توجه کنید:
همانطور که در شکل فوق نشان داده شده است، چون حلقه foreach به نتیجه کوئری نیاز دارد، کوئری تعریف شده اجرا می شود. این همان اجرای با تاخیر است. این روش باعث نمی شود که نتیجه کوئری بعد از اجرا شدن ثابت بماند بلکه در هنگام اجرای دوباره کوئری آخرین تغییرات نیز لحاظ می شود. برای درک بهتر به مثال زیر توجه کنید:
همانطور که مشاهده می کنید، حلقه دوم دوباره کوئری را اجرا می کند و نتیجه اجرا شامل آخرین تغییرات نیز است. این یعنی هر بار که به نتیجه یا مقدار یک کوئری احتیاج باشد، مقدارش به اصطلاح re-evaluate می شود. به این کار lazy evaluation گفته می شود.
پیادهسازی Deferred Execution
با استفاده از کلمه کلیدی yield در زبان سی شارپ می توانید متد افزودنی برای اینترفیس IEnumerable ایجاد کنید که با تاخیر اجرا شود. برای نمونه در مثال زیر ما یک متد افزودنی برای اینترفیس IEnumerable با نام GetTeenAgerStudents ایجاد کرده ایم که لیست دانش آموزان نوجوان را باز می گرداند:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static class EnumerableExtensionMethods { public static IEnumerable<Student> GetTeenAgerStudents(this IEnumerable<Student> source) { foreach (Student std in source) { Console.WriteLine("Accessing student {0}", std.StudentName); if (std.age > 12 && std.age < 20) yield return std; } } } |
کد فوق به گونه ای نوشته شده است که اگر متد اجرا شود، نام دانش آموز به همراه یک پیام در صفحه کنسول چاپ می شود. حال می توانید از این متد مانند نمونه زیر استفاده کنید:
1 2 3 4 5 6 7 8 9 10 11 | IList<Student> studentList = new List<Student>() { new Student() { StudentID = 1, StudentName = "John", age = 13 } , new Student() { StudentID = 2, StudentName = "Steve", age = 15 } , new Student() { StudentID = 3, StudentName = "Bill", age = 18 } , new Student() { StudentID = 4, StudentName = "Ram" , age = 12 } , new Student() { StudentID = 5, StudentName = "Ron" , age = 21 } }; var teenAgerStudents = from s in studentList.GetTeenAgerStudents() select s; foreach (Student teenStudent in teenAgerStudents) Console.WriteLine("Student Name: {0}", teenStudent.StudentName); |
خروجی مثال:
1 2 3 4 5 6 7 8 | Accessing student John Student Name: John Accessing student Steve Student Name: Steve Accessing student Bill Student Name: Bill Accessing student Ram Accessing student Ron |
همانطور که مشاهده می کنید، در هنگام تعریف کوئری، متد ما اجرا نشده است بلکه در زمان استفاده از کوئری در داخل حلقه اجرا شده و پیام مورد نظر را چاپ کرده است.
هیچ نظری ثبت نشده است