واحد دانش و تکنولوژی تبیان زنجان
لایه کش (CL یا Cache Layer)
در مقالات قبلی با ضرورت لایه بندی پروژه ، لایه ارتباط با بانک اطلاعاتی و لایه منطق تجاری و لایه واسط کاربر آشنا شدیم ، در این مقاله قصد دارم یک لایه جدید به پروژه اضافه کنم ، این لایه به افزایش سرعت لود اطلاعات و همچنین بهبود در کارایی سیستم و کاهش فشار بر روی بانک اطلاعاتی کمک زیادی خواهد کرد .
این لایه Cache Layer یا لایه کش نام دارد ، همانطور که میدانید Cache بر خلاف دیتابیس اطلاعات (که اطلاعات را در هارد دیسک ذخیره می کند) را در حافظه جانبی (RAM) ذخیره می کند بنابراین سرعت دسترسی و خواندن و نوشتن اطلاعات بسیار بالا خواهد بود ، بنابراین مکان مناسبی برای ذخیره اطلاعاتی است که به کرات درخواست می شود و به ندرت به روز می گردد .
این لایه حد فاصل لایه BLL و UI قرار میگیرد و باعث می گردد به جای اینکه اطلاعات به صورت مستقیم از دیتابیس درخواست داده شود از کش خوانده شود .
برای شروع کار ابتدا یک پروژه جدید از نوع Class Library به نام CL به Solution اضافه کنید (طبق روال قبل) ، قبل از هر چیز پروژه BLL را در این پروژه Add Refrence نمایید ، سپس یک کلاس به نام CLBase به این پروژه اضافه کنید ، این کلاس شامل Property ها و متدهایی است که در تمام کلاس ها استفاده می شود (مانند کلاس مادر در لایه DAL) .
همانطور که میدانید کلاس Cache در فضا نام System.Web قرار دارد بنابراین باید این فضا نام را به پروژه اضافه کنیم ، برای اینکار وارد منوی Project>Add Refrence شده از تب اول (NET.) فضا نام System.Web را انتخاب کرده و تایید نمایید .
در کلاس CLBase این فضا نام را Using کنید :
using System.Web;
سپس دو Property زیر را اضافه نمایید :
protected string MasterCacheKey { get; set; }
protected double CacheDuration { get; set; }
سپس منتد های زیر را نیز به کلاس بیافزایید ، در نهایت کلاس مادر به شکل زیر خواهد بود :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace CL
{
public class CLBase
{
protected string MasterCacheKey { get; set; }
protected double CacheDuration { get; set; }
protected string GetCacheKey(string cacheKey)
{
return string.Concat(MasterCacheKey, "-", cacheKey);
}
protected object GetCacheItem(string rawKey)
{
return HttpRuntime.Cache[GetCacheKey(rawKey)];
}
protected void AddCacheItem(string rawKey, object value)
{
System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
// Make sure MasterCacheKeyArray[0] is in the cache - if not, add it
if (DataCache[MasterCacheKey] == null)
DataCache[MasterCacheKey] = DateTime.Now;
// Add a CacheDependency
System.Web.Caching.CacheDependency dependency = new System.Web.Caching.CacheDependency(null, new string[] { MasterCacheKey });
DataCache.Insert(GetCacheKey(rawKey), value, dependency, DateTime.Now.AddMinutes(CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration);
}
public void InvalidateCache()
{
// Remove the cache dependency
HttpRuntime.Cache.Remove(MasterCacheKey);
}
}
}
متد اول بسیار سادست ، تنها کاری که میکند این است که نام کلید اصلی کلاس کش را به نام کش مربوط الصاق می کند ، این کار برای جلوگیری از تکرار در نام کش ها است .
متد دوم با دریافت نام Cache آن را از حافظه واکشی می کند و متد سوم وظیفه درج یک آیتم جدید در کش را بر عهده دارد و متد چهارم کش را ریست می نماید .
اکنون که کلاس مادر حاضر شده است به سراغ یکی از کلاس Users رفته و آن را پیاده سازی می کنیم ، برای این کار یک کلاس جدید به نام UsersCL یا Users به این پروژه اضافه کنید ، و آنرا از کلاس مادر یعنی CLBase مشتق نمایید . در سازنده کلاس (Constructor) دو خاصیت MasterCacheKey و CacheDuration را مقدار دهی می کنیم و سپس متد GetUsersByUserID را در لایه کش پیاده سازی می نماییم :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CL
{
public class Users : CLBase
{
public Users()
{
CacheDuration = 60.0;
MasterCacheKey = "UsersCache";
}
public List<BLL.Users> GetUserByUserID(int userId)
{
string rawKey = string.Concat("UserByUserID-", userId);
List<BLL.Users> UserData = GetCacheItem(rawKey) as List<BLL.Users>;
if (UserData == null)
{
UserData = BLL.Users.GetUserByUserID(userId);
AddCacheItem(rawKey, UserData);
}
return UserData;
}
}
}
همانطور که ملاحظه می کنید ابتدا یک نام برای کش درنظر گرفته شده است ، این نام ترکیبی از کلمه UserByUserID و کد کاربری است بنابراین به ازای هر کاربر یک کش در حافظه ذخیره می شود (البته معمولا در این گونه موارد از کش استفاده نمی شود و این جا فقط جنبه آموزشی دارد)
سپس توسط متد GetCacheItem که در کلاس مادر نوشتیم مقدار کش واکشی شده و در یک شی از نوع لیست کلاس BLL.Users ریخته می شود ، واضح است که بار اول که این متد فراخوانی می شود مقدار بازگشتی Null خواهد بود چرا که کشی در کار نیست !
سپس در صورت Null بودن این مقدار اطلاعات از طریق لایه BLL از دیتابیس واکشی شده و توسط متد AddCacheItem در کش ذخیره می شود ، بدیهی است دفعه آتی شرط برقرار نخواهد شد و اطلاعات به جای اینکه از دیتابیس واکشی شود از کش درخواست می گردد .