Download the code for this tutorial
Download this tutorial in PDF format
کش
کردن داده ها :
در
مقاله قبلی ما
یاد گرفتیم که
چگونه در لایه
presentation
بتوانیم
اطلاعات را کش
کنیم. در این
مقاله ما یاد
خواهیم گرفت
که چگونه می
توان یک لایه
برای کش کردن
داده ها به
برنامه
هایمان اضافه
نماییم.
مقدمه
:
همانطور
که در مقاله
گذشته نشان داده
شد، کش کردن داده
ها بوسیله ObjectDataSource تنها
با تنظیم کردن
مجموعه ای از property ها
قابل پیاده
سازی است. متاسفانه
این کنترل کش
کردن داده ها را
در لایه presentation
انجام می دهد
، و طبق صحبت
هایی که در
مقاله اول از
این سری مقالات
صحبت شد، در
توسعه نرم
افزار و
انعطلف پذیری
آن خوب عمل
نمی کند و
بهتر است که
لایه جدیدی
برای این
منظور در نظر
گرفته شود.
برای
مثال لایه Business Logic
، قوانین
تجاری را از
صفحات ASP.NET جدا
می کند ، در
حالی که لایه Data Access جزئیات
دسترسی به
داده ها را
جدا می کند. این
جداسازی ها
بسیارخوب
هستند زیرا باعث
افزایش
خوانایی ،
نگهداری ،
انعطاف پذیری
برنامه ها در
مقابل تغییرات
می شود. سیاست
جدا سازی لایه
presentation از caching نیز به
خاطر همین
دلایل است.
در
این مقاله ما
به معماری
قبلیمان لایه
جدیدی بنام Caching Layer ( یا به طور
خلاصه CL ( که تمامی
عملیات کش
کردن اطلاعات
را مدیریت می
کند ، اضافه
خواهیم کرد. این
لایه شامل
کلاسی بنام ProductsCL که شرایط
مورد نیاز
برای دسترسی
به اطلاعات product
را بوسیله
متدهایی
همچونGetProduct(), GetProductsByCategoryID(categoryID) فراهم می
کند . این
متدها در
ابتدا تلاش می
کنند که
اطلاعات را از
cache استخراج
کنند . اگر cache خالی
باشد، متدهای
مناسبی را از
لایه ProductBLL
فراخوانی
خواهند کرد.
در نهایت
متدهای کلاس ProductBLL دادهای
استخراج شده
را قبل از
برگرداندن ،
کش خواهند
کزد.
همانطور
که شکل 1 نشان
می دهد ، CL (Cache Layer)
مابین لایه
های Presentation و Business Logic قرار می
گیرد.

گام
1 : تولید کلاس
های Caching Layer
در
این مقاله ما
یک لایه کش
بسیار ساده که
تنها شامل کلاس
ProductBL است
را تولید
خواهیم کرد.
ایجاد یک لایه
کش کامل برای
تمام پروژه
ممکن است شامل
ایجاد کلاس های
CategoriesCL, EmployeedCL
و SuppliersCL
و همچنین
تولید متدی در
کلاس های این
لایه برای
دسترسی به
داده باشد .
همچون لایه
های BLL
و DAL
، این لایه
نیز بهتر است
که به عنوان
یک Class Library
Project جدا باشد.
ما دراین جا
آن را در پوشه App_Code
بصورت یک کلاس
پیاده سازی
خواهیم کرد.
برای
اینکه جدا
بودن کلاس های
CL را
از دیگر کلاس
های DAL
و BLL مشخص
تر باشد ،
اجازه دهید تا
یک زیر پوشه
بنام CL
در App_Code
بصورت زیر
ایجاد کنیم و
در نهایت در
آن کلاسی بنام
ProductsCL.cs
قرار می دهیم.
این
کلاس باید
شامل مجوعه
متدهایی
مشابه در کلاس
Business Logic
Layer یعنی ProductBLL باشد. ما
متدهای GetProducts() و GetProductsByCategoryID(categoryID) را در گام 3 و
یک متد UpdateProduct در
گام 4 ایجاد
خواهیم کرد. شما
می توانید
دیگر متدهای ProductsCL و کلاس های CategoriesCL, EmployeesCL و SuppliersCL را
خودتان ایجاد
نمایید.
گام
دوم : خواندن و
نوشتن در داخل
کش
داده کش
شده می تواند
بصورت برنامه
نویسی از داخل
کدهای یک صفحه
و یا از دیگر
کلاس های یک
پروژه ASP.NET مورد
دسترسی قرار
گیرد. برای
خواندن یا
نوشتن از داده
های کش شده از
داخل کد صفحه
می توان از الگوی
زیر استفاده
کرد :
متد insert
کلاس Cache
چند حالت overload شده
دارد. دو حالت Cache[“Key”]=Value و Cache.Insert(Key, Value)
برای اضافه
کردن یک آیتم
به کش با
استفاده از یک
کلید تعیین
شده و بدون
تعیین زمان expire
بکار می روند.
معمولا ، ما
در مورد کش ها
تمایل داریم
که یک زمانی
را برای expire شدن (
براساس dependency و یا
براساس زمان)
در نظر بگیریم
که دو حالت
بعدی متد Insert این شرایط
را فراهم می
کنند.
متدهایی
که در لایه کش
بکار می روند
ابتدا چک می
کنند که آیا
داده درخواست
شده در داخل
کش وجود دارد یا
خیر. اگر داده
درخواست شده
در کش موجود
نباشد، متد
مناسبی را از لایه
BLL
فراخوانی
میکند. سپس
مقدار بدست
آمده کش می شود
و در نهایت آن
را به خروجی
ارسال می کند.
نمودار sequence این
فرایند بشرح
زیر می باشد:
نمودار sequence فرایند
بدست آوردن
داده از لایه
کش
نمودار
sequence نشان داده
شده در بالا
در کلاس های CL
با استفاده از
الگوی زیر
کامل می شود :
در
این جا، Type ، نوع
داده ذخیره
شده در کش است .
اگر یک آیتم
با کلید مشخصی
کش نشده باشد،
مقدار آن
برابر null
خواهد بود و
مقدار آن باید
از متد مناسبی
از لایه BLL
استخراج و به
کش اضافه شود. حتما
مطمئن باشید
که که از
الگوی بالا در
زمان استفاده
از کش ها
استفاده کنید.
نکته : کش داده thread-safe است
، بنابراین
شما نیازی به
همزمان سازی (Synchronize)
دسترسی داده
برای خواندن و
نوشتن ندارید
. در هر حال ،
اگر شما نیاز
دارید که چند
عملیات را
بصورت همزمان
بر روی داده
ها در کش ، بصورت
اتومیک انجام
دهید ، باید
از یک سری از
روش ها همچون
پیاده سازی
قفل ها استفاده
نمایید . برای
اطلاعات
بیشتر به Synchronizing Access to the ASP.NET Cache مراجعه
نمایید.
یک
آیتم را شما
می توانید
بصورت برنامه
نویسی از کش
با استفاده از
متد Remove
بصورت زیر حذف
نمایید:
گام
3 : بازیابی
اطلاعات
محصولات از
کلاس ProductsCL
در این
مقاله ما دو
متد برای
استخراج داده
های بدست آمده
از کلاس ProductCL بنام
های: GetProducts()
و GetProductsByCategoryID(categoryID)
پیاده سازی
خواهیم کرد. هدف
از متد GetProduct() بازیابی
تمامی
محصولات است ،
در حالیکه GetProductByCategoryID(categoryID)
تمامی
محصولات
مربوط به یک
گروه خاص را
بر می گرداند.
کدهای
زیر قسمتی از
متدهای داخل
کلاس ProductCL
را نشان می
دهد:



در
ابتدا بهتر
است که به صفت
های DataObject
و DataObjectMethodAttribute
که به کلاس ها
و متدها اضافه
شده است توجه
کنید . این صفت
ها اطلاعاتی
را برای ObjectDataSource
فراهم می کند
که نشان دهنده
این مطلب است که
باید چه کلاس
ها و متدهایی
در ویزارد های
مربوط به
تنظیم DataSource ظاهر
شود. از
آنجایی که این
می خواهیم در
آینده از
متدها و کلاس
های CL
در آینده در
داخل objectDataSource
های لایه presentation
استفاده شود ،
از این صفت ها
استفاده کرده
ایم.
در
متدهای GetProducts() و GetProductsByCategoryID(categoryID) داده ای که
از متد GetCacheItem(key)
بدست می آید
در یک متغیر
محلی ذخیره می
شود. متد GetCacheItem(key) ، که
به زودی از آن
استفاده
خواهیم کرد ،
یک آیتم مشخص
براساس کلید
پاس داده شده
به آن را بر می
گرداند. اگر
داده ای
براساس کلید
مشخص شده پیدا
نشود ، آن را
از متد مناسبی
از کلاس ProductBLL بازیابی
و با استفاده
از متد AddCacheItem(key, Value) داده
بدست آمده را به
کش اضافه می
کند .
GetCacheItem(key)
از پارامتر
فراهم شده
برایش
مستقیما
استفاده نمی
کند ، اما
بجای آن از
متد GetCacheKey(key)
، که کلیدی با
پیشوند ProductsCache- را
فراهم می کند
، استفاده می
کند.
از کد
مربوط به یک
صفحه ASP.NET
داده کش شده
را می توان با
استفاده از
ویژگی Cache مربوط به
صفحه بصورت Cache[“key”] = value ،
همانطور که در
گام دوم توضیح
داده شده است
می توان
استفاده کزد. از
کلاسی داخل
معماری ما ،
داده کش شده را
نیز با
استفاده از HttpRuntime.Cache یا HttpContext.Current.Cache مورد
دسترسی قرار
داد.
نکته: اگر شما
با استفاده از
Class Library Projects
برنامه تان را
پیاده سازی
کرده باشید ،
برای استفاده
از کلاس های HttpRuntime و HttpContext
نیاز دارید که
System.Web را
به پروژه تان
اضافه کنید.
اگر
آیتم مورد نظر
در کش پیدا
نشود ، متدهای
کلاس ProductsCL
داده را از
لایه BLL
بدست می آورد
و آنرا با
استفاده از
متد AddCacheItem(key,
value) به کش
اضافه می کند.
برای اضافه
کردن value
به کش ، می
توان از کد
زیر استفاده
کرد ، که پس از 60
ثانیه از بین
می رود :
DateTime.Now.AddSeconds(CacheDuration) زمان از
بین رفتن کش
را تعیین می
کند که برابر 60 ثانیه
است و System.Web.Caching.Cache.NoSlidingExpiration مشخص
می کند که هیچ sliding expiration وجود
ندارد . زمانیکه
از این حالت
متد Insert برای
اضافه کردن
کشی استفاده
می کنید ،
تنها می
توانید از یکی
از این دو (absolute و sliding expiry) حالت
استفاده کنید.
اگر شما سعی
کنید که از هر
دو حالت absolute time و time span
استفاده کنید
، متد Insert یک
خطای زمان
اجرا (Exception)
ArgumentException
ایجاد
می کند .
گام 4 : غیر
معتبر کردن کش
در زمان
ویرایش داده
ها
در
بین متدهای
بازیابی داده
، در لایه کش
نیاز است که
متدهای
مشابهی را
همچون لایه BLL برای
اضافه و حذف
داده فراهم کنید
. متدهای
ویرایش داده
در لایه CL
نیازی به
ویرایش داده
کش شده ندارد
، اما بجای آن متدهای
مناسبی را
برای ویرایش
از لایه BLL فراخوانی
می کند و سپس کش
را نامعتبر می
کند .
متد
UpdateProduct نشان داده
شده در زیر نحوه
پیاده سازی
متدهای
ویرایش داده
را در لایه CL
را نشان می
دهد :
در
این مثال متد
مناسب آن از
لایه BLL
فراخوانی می شود،
اما قبل از return
کردن نتیجه
باید کش را
غیر معتبر کرد
. متاسفانه ،
غیر معتبر
کردن داده کار
راحتی نیست ،
زیرا متدهای GetProducts() و GetProductsByCategoryID(categoryID) از کلاس ProductsCL هر کدام
آیتم هایی با
کلید های
مختلف را
اضافه می کنند
و متد GetProductsByCategoryID(categoryID) به ازای هر categoryID یک کش
مختلف اضافه
می کند .
در
زمان غیر
معتبر کردن کش
، ما نیاز
داریم تمامی
آیتم هایی که
ممکن است
بوسیله کلاس ProductsCL اضافه شده
است را باید
حذف کنیم. برای
تکمیل این کار
نیاز است که این
آیتم ها را با
یک dependency در
زمان اضافه
کردن کردن کش
بوسیله متد AddCacheItem(key, value) مرتبط
سازیم. بطور
کلی ، یک cache dependency می تواند
آیتم دیگری در
کش باشد یا یک
فایل در سیستم
فایل و یا
داده ای از یک Microsoft SQL Server database . زمانی که
آن وابستگی
تغییر کند و
یا از کش
برداشته شود ،
آیتم های کش
شده متناسب با
آن بصورت
خودکار از کش
حذف می شوند. در
اینجا ، ما می
خواهیم که
آیتم اضافه
دیگری را به
کش اضافه کنیم
که به عنوان
یک cache
dependency در تمام
آیتم های
اضافه شده
بوسیله کلاس ProductsCL عمل می کند.
به این ترتیب،
تمامی این
آیتم ها را می
توان با حذف cache dependency ، از بین
برد.
اجازه
دهید که متد AddCacheItem(key, value) را با
تغییرات گفته
شده بصورت زیر
بروز کنیم :
MasterCacheKeyArray یک آرایه رشته
ای است که یک
مقدار رشته ProductsCache را نگه می
دارد. در ابتدا
، یک آیتم کش
به کش ها
اضافه می شود
و تاریخ و زمان
اخیر سیستم به
آن انتساب
داده می شود . اگر
این آیتم وجود
داشته باشد ،
بروز رسانی می
شود. سپس، یک cache dependency ایجاد می
شود. سازنده
کلاس CacheDependency چند حالت overloaddependencies
مشخص می کند. که
در اینجا ما
نمی خواهیم از
این حالت
استفاده کنیم
، بنابراین
مقدار آن را
برابر null
قرار داده ایم
. پارامتر دوم
مجموعه ای از
شده دارد،
متدی که در
اینجا
استفاده می
شود احتیاج به
دو آرایه رشته
ای به عنوان
پارامتر
ورودی دارد .
اولین آن
مجموعه از
فایل ها را به
عنوان
کلیدهای
کش را برای
استفاده به عنوان
dependencies مشخص می
کند. در اینجا
تنها یک مورد
را مشخص می
کنیم که همان MasterCacheKeyArray است. در
نهایت CacheDependency به
متد Insert
پاس داده می
شود.
با
استفاده از
تغییرات
اعمال شده بر
روی متد AddCacheItem(key, value)، نامعتبر
کردن کش به
آسانی حذف dependency خواهد
بود .
گام
5 : فراخوانی
متدهای لایه
کش از لایه Presentation
برای
نشان دادن کار
با لایه کش ،
تغییراتی را
که در کلاس ProductsCL داده اید
را ذخیره کنید
و سپس صفحه FromTheArchitecture.aspx را از پوشه Caching باز کنید و
یک GridView
به آن
اضافه کنید.
سپس یک ObjectDataSource
جدید برای آن
ایجاد نمایید.
در اولین
مرحله از
ویزارد تنظیم
این کنترل،
شما باید کلاس
ProductsCL را به صورت
زیر انتخاب
نمایید .
پس
از انتخاب این
کلاس ، دکمه Next
را کلیک کنید .
سپس همانطور
که در زیر
نشان داده شده
است باید
متدهای
مناسبی را
برای Select و Update
انتخاب
نمایید و در
نهایت دکمه Finish
را کلیک
نمایید.
نکته : لایه
کشی که در
برنامه همراه
این مقاله
آمده است کامل
نیست. به
عبارتی تنها
شامل یک کلاس ProductsCL، که تنها شامل
چند متد است و
تنها یکی از
صفحات ASP.NET از
این برنامه از
لایه کش
استفاده می
کند (~/Caching/FromTheArchitecture.aspx) و مابقی
بصورت مستقیم
از لایه BLL
استفاده می
کنند. اگر شما
می خواهید که
از لایه CL
در پرورتان
استفاده
نماییید،
باید برای تمامی
فراخوانی ها
از لایه Presentation
در داخل لایه CL
پاسخ داده
شوند.
خلاصه
:
در
حالیکه کش را
می توان در
لایه Presentation
بوسیله کنترل
هایی همچون SqlDataSource و ObjectDataSource
اعمال کرد ،
بهتر است که
تمام عملیات
مربوط به کش
را بصورت لایه
ای کاملا جدا
در معماریمان
قرار دهیم. در
این مقاله ما
یک لایه کش در
بین Presentation Layer و Business Logic Layer ایجاد
کردیم.
روشی
که در این
مقاله برای کش
کردن بکار
رفته است را اصطلاحا
reactive
loading گویند.
به همراه
عملیات
بارگزاری
همزمان، داده
زمانی در کش
بارگزاری می
شود که یک
درخواست برای
آن ایجاد شود. داده
ها را همچنین
می توان به
روش proactively loaded نیز
کش کرد ، که در
این تکنیک داده
هاد قبل از
اینکه نیاز باشند
در کش قرار می
گیرند.
در
مقاله بعدی ما
از این روش
برای کش کردن
استفاده
خواهیم کرد و
همچنین
خواهیم دید که
چگونه می توان
مقادیر static
را در زمان
راه اندازی
برنامه در کش
ذخیره کرد.
شاد
باشید !
پاییز
86
">بهزاد
عبدالله زاده