کارهایی جهت بالابردن کارآیی Entity Framework #3
نویسنده: امیر هاشم زاده
تاریخ: ۱۳۹۴/۱۱/۱۴ ۹:۲۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
در قسمتهای قبلی (^ و ^) راهکارهایی جهت بالا بردن کارآیی، ارائه شد. در ادامه، به آخرین قسمت این سری اشاره خواهم کرد.
یادآوری: قبل از هر چیز با توجه به این مقاله دانستن این نکته الزامی است که فراخوانی برخی متدها مانند DbSet.Add سبب فراخوانی DataContext.ChangeTracker.DetectChanges خواهند شد.
فرض کنید قصد افزودن 2000 موجودیت دانش آموز را دارید:
for (int i = 0; i < 2000; i++)
{
Pupil pupil = GetNewPupil();
db.Pupils.Add(pupil);
}
db.SaveChanges();
var list = new List<Pupil>();
for (int i = 0; i < 2000; i++)
{
Pupil pupil = GetNewPupil();
list.Add(pupil);
}
db.Pupils.AddRange(list);
db.SaveChanges(); db.Configuration.AutoDetectChangesEnabled = false;
string city = "New York";
List<School> schools = db.Schools
.AsNoTracking()
.Where(s => s.City == city)
.Take(100)
.ToList(); استفاده از متد AsNoTracking در کد بالا سبب خواهد شد 100 مدرسه که در شهر نیویورک وجود دارد توسط EF، بدون تحت نظر گرفتن آنها از بانک اطلاعاتی دریافت شوند و سرباری نیز تحمیل نشود.
معمولا، هنگامی که از EF برای اولین بار استفاده مینمایید، ویوهایی ایجاد میگردد که برای ایجاد کوئریها مورد استفاده قرار میگیرند. این ویوها در طول حیات برنامه فقط یکبار ایجاد میشوند. ولی همین یکبار هم زمانبر هستند. خوشبختانه راههایی وجود دارد که ایجاد این ویوها را در زمان runtime انجام نداد و آن راه، استفاده از ویوهای از پیش کامپایل شده است. یکی از راههای ایجاد این ویوها استفاده از Entity Framework Power Tools است. بعد از نصب اکستنشن، بر روی فایل کانتکست راست کلیک کرده و سپس گزینهی Generate Views را از منوی Entity Framework انتخاب کنید.
توجه داشته باشید که هر تغییری را بعد از ایجاد این ویوها بر روی کانتکست اعمال نمایید، باید آنها را مجددا تولید کنید. برای آشنایی بیشتر با این ویوها به این لینک مراجعه کنید. هم چنین پکیج نیوگتی بنام EFInteractiveViews نیز برای این منظور تهیه و توزیع شده است.
در هنگام شروع به کار با EF، چندین کوئری آغازین بر روی دیتابیس اجرا میشوند. یکی از کوئریهای آغازین جهت تشخیص نسخهی دیتابیس است که همانطور در تصویر زیر مشاهده میکنید، در حدود چند میلی ثانیه میباشد.
با توجه به توضیحات، در صورتیکه اطلاعی از نسخهی دیتابیس دارید، میتوانید این کوئری ابتدایی را تحریف نمایید. برای اینکار میتوان توسط متد ()ResolveManifestToken کلاسی که اینترفیس IManifestTokenResolver را پیاده سازی کرده است، نسخهی دیتابیس را برگردانیم و از یک رفت و برگشت به دیتابیس جلوگیری نماییم.
public class CustomManifestTokenResolver : IManifestTokenResolver
{
public string ResolveManifestToken(DbConnection connection)
{
return "2014";
}
} public class CustomDbConfiguration : DbConfiguration
{
public CustomDbConfiguration()
{
SetManifestTokenResolver(new CustomManifestTokenResolver());
}
} تخریب و از بین بردن کانتکست هنگامی که به آن نیاز نداریم بسیار ضروری است. یکی از روشهای اصولی برای Disposing کانتکست، محصور کردن آن بوسیله دستور Using است (البته فرض بر این است که قرار نیست از الگوهای اشاره شده استفاده نماییم). در صورت عدم تخریب صحیح کانتکست باید منتظر آسیب جدی به کارایی Garbage Collector جهت آزاد سازی منابع مورد استفاده کانتکست و هم چنین باز نمودن اتصالات جدید به دیتابیس باشید.
EF از قابلیتی بنام Multiple Result Sets میتواند بهره ببرد که این قابلیت باعث میشود بر روی یک کانکشن ایجاد شده، یک یا چند درخواست از دیتابیس ارسال و یا دریافت شود که سبب کاهش تعداد رفت و برگشت به دیتابیس میشود. کاربرد دیگر این قابلیت، زمانی است که تاخیر زیادی (latency) بین اپلیکیشن و دیتابیس وجود دارد.
برای فعالسازی کافی است مقدار زیر را در کانکشن استرینگ اضافه نمایید:
MultipleActiveResultSets=True;
در C#5 و EF6 پشتیبانی خوبی از متدهای ناهمگام فراهم شده است و اکثر متدهایی مانند ToListAsync, CountAsync, FirstAsync, SaveChangesAsync و غیره که باعث رفت و برگشت به دیتابیس میشوند امکان پشتیبانی ناهمگام را نیز دارند. البته این قابلیت برای برنامههای یک درخواست در یک زمان شاید مفید نباشد؛ ولی برای برنامههای وبی برعکس. در برنامه وب جهت پشتیبانی از بارگذاری همزمان (concurrent) قابلیت ناهمگام (Async) سبب خواهد شد منابع تا زمان اجرای کوئری به ThreadPool بازگردانده شود و برای سرویس دهی مهیا باشند که باعث افزایش scalability خواهد شد.
در اکثر مواقع کارآیی با حجیم شدن دادهها کاهش پیدا میکند (البته در صورت عدم رعایت اصول استاندارد). بنابراین بررسی کارآیی در محیط هایی با حجم دادههای بالا ضروری است. هیچ چیز بدتر از آن نیست که همه چیز در محیط توسعه خوب و بی نقص باشد ولی در محیط عملیاتی به شکست بیانجامد. به همین جهت سعی کنید از ابزارهای تولید داده (^ و ^ و ^) برای ایجاد دادههای آزمایشی استفاده نمایید. سپس کارآیی کوئری خود را مورد بررسی و آزمایش قرار دهید.
using (var ctx = new MyContext())
{
InteractiveViews
.SetViewCacheFactory(
ctx,
new FileViewCacheFactory(@"C:\MyViews.xml"));
}