正如前面章节所言,缓存ObjectDataSource的数据只需要简单的设置一些属性。然而,它是在表现层对数据缓存,这就与ASP.NET page页面缓存策略(caching policies)紧密的耦合(tightly couples)起来。我们对体系机构分层的原因之一便是打破这种耦合。拿业务逻辑层为例,将业务逻辑从ASP.NET页面脱离出来;而数据访问层将数据访问的细节ASP.NET页面脱离出来。从某种意义来说,将业务逻辑和数据访问细节脱离出来是首先,这样的话使系统更易读、易维护、易修改,便于按模块分工—比如,表现层的开发者对数据库的细节不甚了解也不妨碍其开发工作。当然,将缓存策略从表现层脱离出来也有类似的好处。
本文我们将对层次机构进行扩充,新添一个缓存层(Caching Layer,简称CL)以实施缓存策略。该缓存层包括一个ProductsCL类,该类用类似 GetProducts(), GetProductsByCategoryID(categoryID)等方法来访问产品信息。调用这些方法时先从内存检索数据,如果内存为空则调用业务逻辑层BLL里的ProductsBLL类的相应方法,再从数据访问层DAL返回获取的数据。该ProductsCL类的方法从业务逻辑层BLL获取数据后先对数据缓存后再返回。
如图1所示,缓存层CL位于表现层和业务逻辑层。
图1:在我们的体系结构中缓存层(CL)是单独的一层
第一步:创建缓存层的类
在本文,我们创建的缓存层仅仅包含一个ProductsCL类,它只有几个方法。
完整的缓存层还应该包含CategoriesCL, EmployeesCL, 和SuppliersCL类。有了业务逻辑层BLL和数据访问层DAL,缓存层完全可以当成一个单独的类库工程(Class Library project),不过我们将它作为App_Code文件夹里的一个类来处理。
为了更好的将缓存层类和DAL类、BLL类区分开,我们在App_Code文件夹里创建一个新的子文件夹。在资源管理器里右击App_Code文件夹,选择“新文件夹”,命名为CL,在里面添加新类ProductsCL.cs
图2:添加名为CL的文件夹和名为ProductsCL.cs的类
跟BLL里的ProductsBLL类一样,ProductsCL类应该包含相同的数据访问和修改方法。不过在本文,我们只创建GetProducts()方法(在第3步)和GetProductsByCategoryID(categoryID)方法(在第4步)。你可以在空闲的时候对ProductsCL类进行完善,并创建相应的CategoriesCL, EmployeesCL和 SuppliersCL类
第二步:对Data Cache进行读和写
ObjectDataSource的缓存属性使用ASP.NET data cache来存储从BLL获取的数据。要访问data cache,可以从ASP.NET页面的code-behind classes类或体系结构层(architecture)的类来访问。要通过ASP.NET页面的code-behind classes类对data cache进行读写,可使用如下模式:
// Read from the cache(读) object value = Cache["key"];
// Add a new item to the cache(写)
Cache["key"] = value;
Cache.Insert(key, value);
Cache.Insert(key, value, CacheDependency);
Cache.Insert(key, value, CacheDependency, DateTime, TimeSpan);
Cache class类的Insert方法可以有很多的重载。Cache["key"] = value 和 Cache.Insert(key, value)是相同的,都是向cache添加一个条目(item),不过没有指定expiry(可以理解为缓存持续时间)。更具代表性的是,在我们向cache添加条目的时候指定一个expiry,它要么是dependency(从属体),要么是time-based expiry,又或者两者兼而有之,比如上面的最后2个表达式。
如果所需的数据存储在内存的话,首先调用缓存层的方法返回数据。如果不在内存的话就调用BLL里相应的方法。数据先缓存再返回。就像下面的流程表解析的一样:
图3:如果数据存在于内存的话就调用缓存层的方法。
上图的流程可用如下的模式:
Type instance = Cache["key"] as Type; if (instance == null) { instance = BllMethodToGetInstance(); Cache.Insert(key, instance, ...); } return instance;
其中,Type是缓存在内存中的数据的类型——具体到本文,也就是Northwind.ProductsDataTable;此外,key用于唯一地标识缓存的每一个条目。如果指定了key值的那个条目不在内存中,那么instance就为null,然后用BLL类的某恰当的方法来检索数据,将获得的数据缓存到内存。将instance返回后,它将包含一个对数据的引用(reference to the data),数据要么来自内存,要么是BLL类的返回数据。