SQL ServerPetShop数据看层的数据库访问计划

《解剖PetShop》系列之二

第二、PetShop数据看层的数据库访问计划
以多样一中,我打总体上分析了PetShop的架构设计,并提及了子的概念。从以有开始,我拿依次对各级层开展代码级的分析,以告获得越来越缜密而深切的掌握。在PetShop
4.0遭遇,由于引入了ASP.Net
2.0的片段初特点,所以数据层的情呢愈的大和复杂,包括:数据库访问、Messaging、MemberShip、Profile四部分。在多级二中,我拿介绍有关数据库访问的计划。

在PetShop中,系统要处理的数据库对象分为两好像:一是数码实体,对许数据库中相应的数据表。它们从不作为,仅用于表现对象的数目。这些实体类都叫安放Model程序集中,例如数据表Order对应之实业类OrderInfo,其类图如下: 

这些目标并无具有持久化的法力,简单地游说,它们是当数据的载体,便于工作逻辑针对相应数据表进行读/写操作。虽然这些看似的属性分别映射了数据表的排列,而诸一个靶实例也刚刚对应于数据表的各个一样推行,但这些实体类可连无享有相应之数据库访问能力。

由于数量访问层及业务逻辑层都将本着这些数据实体进行操作,因此先后集Model会给立刻半叠的模块所引述。

老二好像数据库对象则是数量的事情逻辑对象。这里所依靠的政工逻辑,并非业务逻辑层意义及的世界(domain)业务逻辑(从者含义及,我还赞成被用业务逻辑层称为“领域逻辑层”),一般意义及说,这些工作逻辑就是为中心的数据库操作,包括Select,Insert,Update和Delete。由于这些业务逻辑对象,仅具有行一旦同数无关,因此其均给架空为一个独门的接口模块IDAL,例如数据表Order对应之接口IOrder: 

用数据实体和有关的数据库操作分离出来,符合面向对象的振奋。首先,它反映了“职责分开”的规则。将数据实体和那个表现分别,使得两者之间依赖减弱,当数码表现时有发生反时,并无影响Model模块中之数码实体对象,避免了以一个好像职责过多、过怪,从而造成该类的引用者发生“灾难性”的影响。其次,它反映了“抽象”的旺盛,或者说是“面向接口编程”的最佳体现。抽象的接口模块IDAL,与具体的数据库访问实现全切断。这种与落实无关之计划性,保证了系的可是扩展性,同时也准保了数据库的可移植性。在PetShop中,可以支撑SQL
Server和Oracle,那么其具体的贯彻就各自位于两单不等的模块SQLServerDAL、OracleDAL中。

因Order为例,在SQLServerDAL、OracleDAL两单模块中,有两样之贯彻,但其又以都落实了IOrder接口,如图: 

从今数据库的兑现来拘禁,PetShop体现出了没ORM框架的层和丑陋。由于要本着数据表进行Insert和Select操作,以SQL
Server为例,就采取了SqlCommand,SqlParameter,SqlDataReader等目标,以成功这些操作。尤其复杂的凡Parameter的传递,在PetShop中,使用了大气底字符串常量来保存参数的称号。此外,PetShop还专门为SQL
Server和Oracle提供了纸上谈兵的Helper类,包装了有些常用的操作,如ExecuteNonQuery、ExecuteReader等措施。

当没有ORM的情形下,使用Helper类是一个较好之方针,利用其来成功数据库基本操作的包裹,可以减掉过多以及数据库操作有关的代码,这反映了对象复用的条件。PetShop将这些Helper类统一置于DBUtility模块中,不同数据库的Helper类暴露的点子基本相同,只除了片异之求,例如Oracle中拍卖bool类型的章程就是跟SQL
Server不同,从而专门供了OraBit和OraBool方法。此外,Helper类中之道均为static方法,以利调用。OracleHelper的类图如下: 

对数据访问层来说,最头疼的是SQL语句的拍卖。在前期的CS结构被,由于无运三层式架构设计,数据看层以及事务逻辑层是紧密糅合在一起的,因此,SQL语句遍布与系统的诸一个角。这为程序的掩护带来巨大的不方便。此外,由于Oracle使用的凡PL-SQL,而SQL
Server和Sybase等下的凡T-SQL,两者虽然都按了正规SQL的语法,但在许多细节及仍发生分别,如果用SQL语句大量之施用到程序中,无疑也可能的数据库移植也带动了困难。

最好的主意是采取储存过程。这种方法教程序更为干净,此外,由于存储过程得因数据库脚本的款式在,也造福移植和改动。但这种方法还是发生瑕疵。一是储存过程的测试相对困难。虽然来对应的调试工具,但比从针对代码的调节而言,仍然比较复杂且无便民。二凡是本着系统的更新带来阻力。如果数据库访问是出于程序完成,在.Net平台下,我们只有得在修改程序后,将再编译的次第集xcopy到布置的服务器上即可。如果采用了储存过程,出于安全之考虑,必须发专门的DBA重新运行存储过程的剧本,部署的办法遭到了限。

自己已在一个列被,利用一个特地的表来存放SQL语句。如一旦运用相关的SQL语句,就运重点字搜索得到对许谈。这种做法近似于储存过程的调用,但却避免了安排上的题目。然而这种方法也以性质达到无法取得保险。它就副吃SQL语句较少之观。不过,利用好的统筹,我们得以呢各种业务提供不同的表来存放SQL语句。同样的道理,这些SQL语句也得存放到XML文件中,更便于系统的扩张或修改。不过前提是,我们用为其提供专门的SQL语句管理工具。

SQL语句之动无法避免,如何重新好的下SQL语句也无定论,但来一个准值得咱们遵守,就是“应该尽量让SQL语句尽存在于数量访问层的切实可行落实中”。

自然,如果采用ORM,那么所有就变换得差了。因为ORM框架已经也数访问提供了基本的Select,Insert,Update和Delete操作了。例如当NHibernate中,我们好直接调用ISession对象的Save方法,来Insert(或者说是Create)一个数额实体对象:
public void Insert(OrderInfo order)
{
    ISession s = Sessions.GetSession();
    ITransaction trans = null;
    try
    {
    trans = s.BeginTransaction();
      s.Save( order);
      trans.Commit();
    }
    finally
    {
      s.Close();
    }
}

莫SQL语句,也从不那些烦人的Parameters,甚至不欲专门去考虑工作。此外,这样的计划性,也是和数据库无关的,NHibernate可以经过Dialect(方言)的机制支持不同的数据库。唯一要召开的凡,我们用为OrderInfo定义hbm文件。

本,ORM框架并非是全能的,面对纷繁复杂的工作逻辑,它并无可知完全消灭SQL语句,以及替代复杂的数据库访问逻辑,但她却非常好的体现了“80/20(或90/10)法虽”(也被叫做“帕累托法则”),也不怕是说:花比较少(10%-20%)的劲就得化解大部分(80%-90%)的题材,而使解决剩下的少部分题目虽需要多得几近之用力。至少,那些当多少访问层中据为己有了多方底CRUD操作,通过运用ORM框架,我们不怕只是需要交极个别光阴和精力来解决它们了。这活脱脱缩短了全项目开之周期。

或者回对PetShop的讨论上来。现在我们都起了数额实体,数据对象的空洞接口和贯彻,可以说关于数据库访问的本位就曾就了。留待我们的还有个别只问题亟待缓解:
1、数据对象创建的管理
2、利于数据库的移植

在PetShop中,要创造的数据对象包括Order,Product,Category,Inventory,Item。在前面的设计中,这些目标就深受架空为对应的接口,而那个落实则基于数据库的不比而有所不同。也就是说,创建的对象有强列,而各种档次又出异的贯彻,这是独立的泛工厂模式的用场景。而地方所陈述之有限独问题,也都可经架空工厂模式来化解。标准的悬空工厂模式类图如下: 

诸如,创建SQL Server的Order对象如下:
PetShopFactory factory = new SQLServerFactory();
IOrder = factory.CreateOrder();

倘若考虑到数据库的可移植性,则factory必须作为一个全局变量,并以主程序运行时吃实例化。但这样的设计则就达了“封装变化”的目的,但以开立PetShopFactory对象时,仍不可避免的起了现实的类SQLServerFactory,也不怕凡说,程序在斯局面达到发生了同SQLServerFactory的强依赖。一旦通系统要求支持Oracle,那么还需要修改就行代码为:
PetShopFactory factory = new OracleFactory();

修改代码的这种作为肯定是不足承受的。解决的道是“依赖注入”。“依赖注入”的作用通常是为此专门的IoC容器提供的,在Java平台下,这样的器皿包括Spring,PicoContainer等。而以.Net平台下,最普遍的虽是Spring.Net。不过,在PetShop系统面临,并不需要专门的容器来兑现“依赖注入”,简单的做法要利用配置文件及反光功能来促成。也就是说,我们可以在web.config文件中,配置好实际的Factory对象的共同体的类名。然而,当我们采取配置文件与反光功能时,具体工厂的缔造就展示有些“画蛇添足”了,我们全好于布局文件中,直接指向具体的数据库对象实现类似,例如PetShop.SQLServerDAL.IOrder。那么,抽象工厂模式中之系工厂便可简化为一个厂子类了,所以自己以这种模式称之为“具有简易工厂特质的抽象工厂模式”,其类图如下: 

DataAccess类完全代表了前方创建的厂子类系,它是一个sealed类,其中创建各种数码对象的方,均为静态方法。之所以会因此此仿佛及抽象工厂的目的,是因安排文件以及反光的下,如下的代码片断所示:
public sealed class DataAccess
{
 // Look up the DAL implementation we should be using
    private static readonly string path =
ConfigurationManager.AppSettings[“WebDAL”];
    private static readonly string orderPath =
ConfigurationManager.AppSettings[“OrdersDAL”];

 public static PetShop.IDAL.IOrder CreateOrder()
 {
         string className = orderPath + “.Order”;
         return
(PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className);
    }
}

于PetShop中,这种借助配置文件与反光创建对象的点子最广泛,包括IBLLStategy、CacheDependencyFactory等等。这些实现逻辑散布于全体PetShop系统中,在我看来,是得当此基础及展开重构的。也就是说,我们可吗整个体系提供类似于“Service
Locator”的落实:
public static class ServiceLocator
{
 private static readonly string dalPath =
ConfigurationManager.AppSettings[“WebDAL”];
    private static readonly string orderPath =
ConfigurationManager.AppSettings[“OrdersDAL”];
 //……
 private static readonly string orderStategyPath =
ConfigurationManager.AppSettings[“OrderStrategyAssembly”];

 public static object LocateDALObject(string className)
 {
  string fullPath = dalPath + “.” + className;
  return Assembly.Load(dalPath).CreateInstance(fullPath);
 }
public static object LocateDALOrderObject(string className)
 {
  string fullPath = orderPath + “.” + className;
  return Assembly.Load(orderPath).CreateInstance(fullPath);
 }
public static object LocateOrderStrategyObject(string className)
 {
  string fullPath = orderStategyPath + “.” + className;
  return Assembly.Load(orderStategyPath).CreateInstance(fullPath);
 }
 //……
}

那和所谓“依赖注入”相关的代码都可以用ServiceLocator来成功。例如类DataAccess就得简化为:
public sealed class DataAccess
{
 public static PetShop.IDAL.IOrder CreateOrder()
 {
         return (PetShop.IDAL.IOrder)ServiceLocator.
LocateDALOrderObject(“Order”);
    }
}

由此ServiceLocator,将兼具与安排文件有关的namespace值统一管理起,这便于各种动态创建对象的管住以及未来的保安。

相关文章