PetShop数据访问层之数据库访问布署

《解剖PetShop》种类之贰

二、PetShop数据访问层之数据库访问布置
在多元一中,小编从总体上分析了PetShop的架构划设想计,并谈到了分支的定义。从本有的起始,笔者将顺序对各层举行代码级的剖析,以求获得进一步细心而深深的知道。在PetShop
四.0中,由于引进了ASP.Net
2.0的部分新特征,所以数据层的始末也特别的广泛和复杂性,包罗:数据库访问、Messaging、MemberShip、Profile四部分。在多种第22中学,笔者将介绍有关数据库访问的规划。

在PetShop中,系统供给处理的数据库对象分为两类:一是数码实体,对应数据库中相应的数据表。它们从不作为,仅用于表现对象的多少。那么些实体类都被放到Model程序集中,例如数据表Order对应的实体类OrderInfo,其类图如下: 

图片 1

这一个指标并不负有持久化的意义,不难地说,它们是作为数据的载体,便于工作逻辑针对相应数据表进行读/写操作。即使那个类的品质分别映射了数据表的列,而每3个指标实例也恰好对应于数据表的每1行,但那个实体类却并不享有相应的数据库访问能力。

出于数量访问层和作业逻辑层都将对那一个数据实体实行操作,由此先后集Model会被那两层的模块所引述。

其次类数据库对象则是数据的事务逻辑对象。那里所指的事务逻辑,并非业务逻辑层意义上的圈子(domain)业务逻辑(从那些意思上,小编更赞成于将事情逻辑层称为“领域逻辑层”),1般意义上说,这个工作逻辑即为基本的数据库操作,包罗Select,Insert,Update和Delete。由于这几个业务逻辑对象,仅具有行为而与数据非亲非故,因而它们均被架空为贰个独立的接口模块IDAL,例如数据表Order对应的接口IOrder: 

图片 2

将数据实体与相关的数据库操作分离出来,符合面向对象的精神。首先,它显示了“任务分开”的尺度。将数据实体与其作为分别,使得两者之间重视减弱,当数码作为时有发生转移时,并不影响Model模块中的数据实体对象,幸免了因一个类职务过多、过大,从而导致该类的引用者发生“灾祸性”的熏陶。其次,它显示了“抽象”的动感,只怕说是“面向接口编制程序”的一流体现。抽象的接口模块IDAL,与现实的数据库访问达成完全隔开分离。那种与落到实处非亲非故的宏图,保障了系统的可扩充性,同时也保障了数据库的可移植性。在PetShop中,能够帮忙SQL
Server和Oracle,那么它们具体的落成就各自位居四个例外的模块SQLServerDAL、OracleDAL中。

以Order为例,在SQLServerDAL、OracleDAL多个模块中,有两样的兑现,但它们同时又都落到实处了IOrder接口,如图: 

图片 3

从数据库的完结来看,PetShop显示出了从未有过O哈弗M框架的重叠与丑陋。由于要对数据表进行Insert和Select操作,以SQL
Server为例,就动用了SqlCommand,SqlParameter,SqlDataReader等指标,以形成这几个操作。尤其复杂的是Parameter的传递,在PetShop中,使用了大气的字符串常量来保存参数的名目。其它,PetShop还专程为SQL
Server和Oracle提供了用空想来欺骗别人的Helper类,包装了部分常用的操作,如ExecuteNonQuery、ExecuteReader等办法。

在一直不O奥迪Q5M的事态下,使用Helper类是1个比较好的策略,利用它来形成数据库基本操作的卷入,可以减去过多和数据库操作有关的代码,这反映了目的复用的准绳。PetShop将那几个Helper类统1置于DBUtility模块中,差别数据库的Helper类暴光的不贰法门基本相同,只除了部分特殊的供给,例如Oracle中处理bool类型的方法就和SQL
Server差别,从而专门提供了OraBit和OraBool方法。此外,Helper类中的方法均为static方法,以利于调用。OracleHelper的类图如下: 

图片 4

对此数据访问层来说,最发烧的是SQL语句的处理。在初期的CS结构中,由于未选拔3层式架构划设想计,数据访问层和事情逻辑层是紧凑糅合在联合的,由此,SQL语句遍布与系统的每2个角落。那给程序的维护带来巨大的困顿。此外,由于Oracle使用的是PL-SQL,而SQL
Server和Sybase等采取的是T-SQL,两者即便都依照了标准SQL的语法,但在很多细节上仍有分别,假诺将SQL语句多量的施用到程序中,无疑为大概的数据库移植也推动了艰巨。

最棒的格局是选用储存进度。这种办法使得程序更为卫生,其它,由于存款和储蓄进度能够以数据库脚本的款式存在,也有利于移植和改动。但这种格局如故有弱点。一是储存进程的测试相对困难。尽管有照应的调节工具,但比起对代码的调节和测试而言,照旧相比复杂且不便利。二是对系统的翻新带来阻力。若是数据库访问是由程序完结,在.Net平台下,大家仅要求在改动程序后,将再度编写翻译的主次集xcopy到安插的服务器上即可。要是使用了仓库储存进程,出于安全的思索,必须有专门的DBA重国民党的新生活运动行存款和储蓄进程的本子,安顿的办法遭到了限定。

本人一度在三个项目中,利用多个特意的表来存放SQL语句。如要使用有关的SQL语句,就选取重点字搜索得到对应语句。那种做法近似于存款和储蓄进度的调用,但却防止了配备上的难点。然则那种格局却在性质上不能够获取保险。它仅符合于SQL语句较少的气象。可是,利用得天独厚的宏图,大家得以为种种业务提供差异的表来存放SQL语句。同样的道理,这么些SQL语句也足以存放到XML文件中,更有益于系统的扩展或修改。然则前提是,大家必要为它提供专门的SQL语句管理工科具。

SQL语句的选取不可能避免,怎么样更好的使用SQL语句也无定论,但有一个规格值得咱们遵从,正是“应该尽量让SQL语句尽存在于数量访问层的切实可行落到实处中”。

当然,假使运用ORubiconM,那么整个就变得不如了。因为O瑞虎M框架已经为数量访问提供了中央的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文件。

当然,O大切诺基M框架并非是文武兼资的,面对纷纭复杂的作业逻辑,它并无法完全消灭SQL语句,以及代表复杂的数据库访问逻辑,但它却很好的反映了“80/20(或90/十)法则”(也被称之为“帕累托法则”),也等于说:花比较少(一成-2/10)的劲头就能够缓解大多数(五分之四-十分九)的难点,而要化解剩余的少部分题材则必要多得多的竭力。至少,那么些在数据访问层中据为己有了多方的CRUD操作,通过利用O君越M框架,我们就仅要求提交极个别日子和生命力来消除它们了。那如实裁减了上上下下项目支出的周期。

要么回到对PetShop的议论上来。未来大家已经有了数码实体,数据对象的空洞接口和贯彻,能够说关于数据库访问的重心就已经到位了。留待大家的还有七个难题亟需消除:
一、数据对象创设的军管
2、利于数据库的移植

在PetShop中,要开创的数量对象包涵Order,Product,Category,Inventory,Item。在前面包车型客车筹划中,这个目的已经被架空为对应的接口,而其完结则依据数据库的不等而有所分歧。也便是说,创设的指标有八种档次,而每连串型又有例外的完成,那是数1数二的充饥画饼工厂格局的应用场景。而地方所述的五个难题,也都得以透过架空工厂形式来缓解。标准的悬空工厂方式类图如下: 

图片 5

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

要思虑到数据库的可移植性,则factory必须作为2个全局变量,并在主程序运维时被实例化。但诸如此类的安排性固然一度高达了“封装变化”的指标,但在创立PetShopFactory对象时,仍不可幸免的产出了切实的类SQLServerFactory,相当于说,程序在这几个局面上产生了与SQLServerFactory的强重视。一旦整个种类供给帮忙Oracle,那么还索要修改这行代码为:
PetShopFactory factory = new OracleFactory();

修改代码的那种行为强烈是不可接受的。消除的章程是“依赖注入”。“注重注入”的职能平日是用越发的IoC容器提供的,在Java平台下,那样的容器包罗Spring,PicoContainer等。而在.Net平台下,最普遍的则是Spring.Net。然则,在PetShop系统中,并不须求专门的器皿来兑现“注重注入”,简单的做法依然采用配置文件和反光功用来促成。也正是说,大家得以在web.config文件中,配置好实际的Factory对象的全体的类名。可是,当大家选择配置文件和反光成效时,具体育工作厂的创始就呈现有些“画蛇添足”了,我们全然能够在布局文件中,直接针对具体的数据库对象达成类,例如PetShop.SQLServerDAL.IOrder。那么,抽象工厂形式中的相关工厂就能够简化为一个厂子类了,所以本身将那种形式称之为“具有简易工厂特质的虚幻工厂方式”,其类图如下: 

图片 6

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中,那种借助配置文件和反光创造对象的不2秘籍最棒广泛,包括IBLLStategy、CacheDependencyFactory等等。那几个达成逻辑散播于全数PetShop系统中,在作者眼里,是能够在此基础上进展重构的。也正是说,大家得以为壹切连串提供类似于“ServiceLocator”的贯彻:
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值统壹管理起来,那有利于种种动态成立对象的管住和前程的保证。

相关文章