کتابخانه sammy
LINQ در JavaScript
-
تنها دریافت رکوردهای مورد نیاز
string city = "New York"; List<School> schools = db.Schools.ToList(); List<School> newYorkSchools = schools.Where(s => s.City == city).ToList();
در کد بالا ابتدا کلیه ردیفهای جدول از دیتابیس به حافظه منتقل میشود و سپس برروی آنها کوئری مورد نظر اعمال میگردد که بشدت میتواند برای یک برنامه - خصوصا برنامه وب - بهدلیل دریافت کلیهی ردیفهای جدول بسیار مخرب باشد. کوئری فوق را میتوان به صورت زیر اصلاح کرد:
List<School> newYorkSchools = db.Schools.Where(s => s.City == city).ToList(); یا IQueryable<School> schools = db.Schools; List<School> newYorkSchools = schools.Where(s => s.City == city).ToList();
-
حداقل رفت و برگشت به دیتابیس
کد زیر را در نظر بگیرید:
string city = "New York"; List<School> schools = db.Schools.Where(s => s.City == city).ToList(); var sb = new StringBuilder(); foreach(var school in schools) { sb.Append(school.Name); sb.Append(": "); sb.Append(school.Pupils.Count); sb.Append(Environment.NewLine); }
هدف تکه کد بالا این است که تعداد دانش آموزان مدرسههای واقع در شهر New York را بدست آورد.
توجه داشته باشید:
- یک مدرسه میتواند چندین دانش آموز داشته باشد (وجود رابطه یک به چند)
- LazyLoading فعال است
- تعداد مدرسههای شهر نیویورک 200 عدد میباشد
اگر کوئری بالا را بهوسیلهی یک پروفایلر بررسی نمایید، متوجه خواهید شد 1 + 200 رفت و برگشت به دیتابیس صورت گرفته است که به "N+1 select problem" معروف است. 1 مرتبه جهت دریافت لیست مدرسههای شهر نیویورک و 200 مرتبه جهت دریافت تعداد دانش آموزان هر مدرسه.
بدلیل فعال بودن Lazy Loading، زمانیکه موجودیتی فراخوانی میشود، سایر موجودیتهای وابسته به آن، زمانی از دیتابیس فراخوانی خواهند شد که به آنها دسترسی پیدا کنید. در حلقهی foreach هم به ازای هر مدرسه (200 مدرسه) شهر نیویورک یک رفت و برگشت انجام میشود.
اما راه حل در این مورد خاص استفاده از Eager Loading است. خط دوم کد را بصورت زیر تغییر دهید:
List<School> schools = db.Schools .Where(s => s.City == city) .Include(x => x.Pupils) .ToList();
حال با یک رفت و برگشت، همراه هر مدرسه اطلاعات مربوط به دانش آموزان وابستهی آن نیز در دسترس خواهد بود.
-
تنها استفاده از ستونهای مورد نیاز
فرض کنید قصد دارید نام و نام خانوادگی دانش آموزان یک مدرسه را بدست آورید.
int schoolId = 1; List<Pupil> pupils = db.Pupils .Where(p => p.SchoolId == schoolId) .ToList(); foreach(var pupil in pupils) { textBox_Output.Text += pupil.FirstName + " " + pupil.LastName; textBox_Output.Text += Environment.NewLine; }
- انتقال اطلاعات بلا استفاده که ممکن است باعث کاهش کارآیی Sql Server I/O و شبکه و اشغال حافظهی کلاینت گردد.
- کاهش کارآیی ایندکس گذاری. فرض کنید برروی جدول دانش آموزان ایندکسی شامل 2 ستون نام و نام خانوادگی تعریف کردهاید. با انتخاب تمام ستونهای جدول توسط خط دوم (select * from...) به کارآیی ایندکس گذاری برروی این جدول آسیب زدهاید. توضیح بیشتر در اینجا مطرح شده است.
اما راه حل:
var pupils = db.Pupils .Where(p => p.SchoolId == schoolId) .Select(x => new { x.FirstName, x.LastName }) .ToList();
-
عدم تطابق نوع ستون با نوع خصیصه مدل
فرض کنید نوع ستون جدول دانش آموزان (VARCHAR(20 است و خصیصه کدپستی مدل دانش آموز مانند زیر تعریف شده است:
public string PostalZipCode { get; set; }
انتخاب نوع داده و تطابق نوع داده مدل با ستون جدول دارای اهمیت زیادی است و در صورت عدم رعایت، باعث کاهش کارآیی شدید میگردد. در کد زیر قصد دارید لیست نام و نام خانوادگی دانش آموزانی را که کدپستی آنها 90210 میباشد، بدست بیاورید.
string zipCode = "90210"; var pupils = db.Pupils .Where(p => p.PostalZipCode == zipCode) .Select(x => new {x.FirstName, x.LastName}) .ToList();
هنگامیکه کوئری بالا را اجرا نمایید، زمان زیادی جهت اجرای آن صرف خواهد شد. در صورتی که از یک پروفایلر استفاده نمایید، میتوانید عملیات پرهزینه را شناسایی نمایید و اقدام به کاهش هزینهها کنید.
همانطور که در شکل بالا مشخص است عملیات index scan از سایر عملیاتها پرهزینهتر است. حال به بررسی علت بهوجود آمدن این عملیات پرهزینه خواهیم پرداخت.
Index Scan زمانی رخ میدهد که اس کیو ال سرور مجبور است هر صفحهی از ایندکس را بخواند و شرایط را (کدپستی برابر 90210) اعمال نماید و نتیجه را برگرداند. Index Scan بسیار هزینه بر است، چون اس کیو ال سرور، کل ایندکس را بررسی مینماید. نقطهی مقابل و بهینهی آن، Index Seek است که اس کیو ال سرور به صفحهی مورد نظر ایندکسی که به شرایط نزدیکتر است، منتقل میگردد.
خب چرا اس کیو ال سرور Index Scan را بجای Index Seek انتخاب کرده است؟!
اشکالی در قسمت سمت چپ شکل بالا که به رنگ قرمز نمایش داده شده است، وجود دارد:
Type conversion: Seek Plan for CONVERT_IMPLICIT(nvarchar(20), [Extent1].[PostalZipCode],0)=[@p__linq__0]
پارامتر کوئری تولید شدهی توسط EF از نوع NVARCHAR است و تبدیل نوع NVARCHAR پارامتر کدپستی، که محدودهی اطلاعات بیشتری (Unicode Strings) را نسبت به نوع VARCHAR ستون دارد، بهدلیل از دست رفتن اطلاعات امکان پذیر نیست. بههمین جهت برای مقایسهی پارامتر کدپستی با ستون VARCHAR ، اس کیو ال سرور باید هر ردیف ایندکس را از VARCHAR به NVARCHAR تبدیل نماید که منجر به Index Scan میشود. اما راه حل بسیار ساده این است که فقط نوع خصیصه را با ستون جدول یکسان کنید.
[Column(TypeName = "varchar")] public string PostalZipCode { get; set; }
I think that JavaScript's loose typing is one of its best features and that type checking is way overrated. TypeScript adds sweetness, but at a price. It is not a price I am willing to pay.
اما به مرور زمان این زبان توفیق بیشتری پیدا کرد تا اینکه امروز پروژههای بسیار جالبی با این زبان در حال توسعه هستند.
چرا باید در مورد Typescript بدانیم؟
زبان Typescript نقاط قوت بسیاری دارد، از جملهی آنها میتوان به موارد زیر اشاره کرد:
- این زبان یکی از مشکلات اصلی JavaScript را که نبودن Type Safety میباشد حل کردهاست. اگر چه زبانی که type safe نباشد بسیاری اوقات مزیت است! زبان typescript در حقیقت یک زبان gradual typing است.
- از آنجایی که typescript یک super set از زبان JavaScript است، برنامهنویس در لحظه از مزایای زبان JavaScript هم بهرهمند است. مهمتر از آن این است که در زبان typescript به اقیانوس کتابخانههای JavaScript دسترسی دارید. این امکان در بسیاری زبانهای دیگر جایگزین JavaScript وجود ندارد. حتی بهتر از آن، میتواند با این کتابخانهها بهصورت type safe برنامه بنویسید. تصور کنید که وقتی با $ در JQuery کار میکنید بتوانید از امکان intellisense استفاده کنید.
- بازهم از آنجا که typescript یک super set از JavaScript است، typescript قرار نیست به اسمبلی کامپایل شود؛ بلکه به زبان شناخته شدهای به نام JavaScript تبدیل میشود. بنابراین حتی میتوان از آن JavaScript نیز یاد گرفت.
- کار با زبان typescript برای کسانی که با java یا سی شارپ آشنا هستند، راحت است. امکاناتی مانند genericها نیز در typescript وجود دارد.
- نقشهی راه typescript با EcmaScript هماهنگ است. بنابراین از یادگرفتن این زبان ضرر نمیکنید چون قابلیتهای این زبان را به احتمال زیاد در نسخهی بعدی EcmaScript خواهید دید.
- این زبان توسط شرکت مایکروسافت پشتیبانی میشود، اوپن سورس است و تجربهی Anders Hejlsberg در زمینهی طراحی زبانهای برنامهنویسی پشتیبان آن!
- پروژههای جالبی که در ادامه به معرفی آنها میپردازیم، با این زبان در حال توسعه هستند.
در این مطلب تعدادی از این پروژهها را که برای خودم جذاب هستند، به شما معرفی میکنم.