PetShop3.x学习笔记6-SQLServer学习笔记

一、 SQLServer主要功能:

1、              这是Microsoft SQL Server特定的PetShop DAL层实现,执行了IDAL接口定义的各方法

 

二、 实现细节:

1、              SQLHelper.cs文件:就是MS DAAB

2、              主要定义了以下几个方法对数据库操作:

3、              ExecuteNonQuery()方法用于根据用户的要求(SQL语句)对数据库执行操作,这包括3个重载方法

4、              注意:ExecuteNonQuery()方法接受的SQL语句的参数,是一SqlParameter[]数组的形式出现的!!!这样的设计方法,避免了由于不同SQL语句中的参数个数不同,而为每一个不同的SQL语句定义一个ExecuteNonQuery()方法的问题!!!而改由“SQL语句模板“SqlParameter[]变量数组自动进行变量对应!!!!!!

5、              ExecuteReader()方法根据用户的要求(SQL语句)对数据库执行查询,并返回给用户一个包含特定查询结果的SqlDataReader,供调用程序(用户)使用

6、              ExecuteScalar()方法,用于根据用户的要求(SQL语句)对数据库执行查询,并返回查询所返回的结果集中第一行的第一列,而忽略额外的列或行,这包括两个重载方法

7、              CacheParameters()方法,用于将SqlParameter[]数组存储在Hashtable中,并用一个进行标识

8、              GetCachedParameters()方法,用于将CacheParameters()方法存储在Hashtable中的SqlParameter[]数组,根据设置好的进行提取

9、              Account.cs文件:实现了IDAL中定义的方法

10、          SignIn()方法为例,SignIn()方法的功能是解决用户账户登录的整个问题,该方法中包含两部分,一部分是逻辑判断和操作,还有一部分是与数据库交互。逻辑判断部分一般以数据库交互的结果为依据,给调用程序返回合适的结果

11、          变量添加到SqlParameter[]数组的顺序一定要和在SQL模板中定义的变量的顺序一致!!!

12、          SignIn()方法为例,演示SQLServer DAL实现在IDAL中定义的某一个方法过程:

(1)        BLL层调用IDAL接口层的Account类的SignIn()方法

(2)        IDAL接口实际是使用DAL层的Account类的SignIn()方法

(3)        由于Account类就是针对Account数据库表进行操作的,所以在Account类当中,对Account数据库表进行增删改查的SQL语句都已经写成了模板

(4)        在用户(BLL层)调用SignIn()方法的时候,肯定提供了相应的变量,如用户名UserId和密码Password,这些都对应于SQL语句模板当中需要的变量

(5)        为了满足使用“SQLHelper类的方法的格式,所以要把用户传入的变量(UserIdPassword),也就是SQL语句模板需要的变量,都包装在一个SqlParameter[]数组当中,将所有参数作为一个数组传递给SQLHelper类的相应方法,进行操作

(6)        返回一个新SqlParameter[]数组的方法也有讲究!!!这里在SignIn()方法中又调用了一个GetSignOnParameters()方法!!!

(7)        这个GetSignOnParameters()方法首先判断,如果在SQLHelper.csHashtable中存在(缓存了)一个空的SqlParameter[]变量数组(也相当于模板),则直接将此空的SqlParameter[]变量数组(模板)返回给调用程序(也就是SignIn()方法);相反,若不存在这样一个空的SqlParameter[]变量数组(模板),则根据向SignOn表中插入数据的SQL语句模板(对变量的需求),创建一个空的SqlParameter[]变量数组(模板),并缓存在SQLHelperHashtable当中,然后返回给调用程序。

(8)        这里有一个重要的内容!!!Hashtable parmCache究竟缓存的是什么内容!!!实际上,parmCache缓存的是各“SQL语句模板对应(使用)的空白SqlParameter[]变量数组(模板)!!!这个数组不是针对某个实例的(这里的某个实例指的是某一套用户名和密码,如用户名为A,密码为B),而是空白的、通用的、针对某个“SQL语句模板“SqlParameter[]变量数组(模板)!!!!!!

(9)        PetShop在这里使用缓存参数数组模板的方式,是为了提高性能,不必每次都为一个用户的登录(每套用户名和密码实例)而建立一个新的“SqlParameter[]变量数组

(10)    这里终于理解了为什么GetCacheParameter()方法,就算查找到有对应的“SqlParameter[]变量数组(模板)也不直接返回,而是Clone一个之后再返回!!!完全是因为在Hashtable中,我们需要存储的只是一个“SqlParameter[]变量数组(模板),而不是一套用户名和密码的实例!!!如果直接返回存储在Hashtable中的“SqlParameter[]变量数组,则在不同的用户登录后,都会改写模板的内容,相当于将模板实例化了,而这是错误的!!!

(11)    SignIn()方法得到了一个空白的“SqlParameter[]变量数组时,就根据调用SignIn()方法时提供的具体用户名和密码,初始化这个“SqlParameter[]变量数组。而这个“SqlParameter[]变量数组正是SQLHelperExecuteReader()方法需要的参数(类型)之一!!!

(12)    根据用户登录动作时提供的用户名和密码信息,在数据库中去找对应的条目(默认用户的输入总是正确的)。如果找到了,则认为用户登录是成功的,并且直接读取用户的其他个人信息,实例化成为一个AccountInfo(在Model中定义)类型的对象,返回给BLL调用程序!!!!!!

13、          GetAddress()方法的实现方式与SignIn()方法相同

14、          Insert()方法:用于向数据库中插入一条新的用户账户信息

15、          由于需要将一个用户注册的信息分别写入3个数据库表当中,为避免写入的过程中发生问题,这里使用一个事务,将3个写入操作打成一个”——要么全部执行成功,要么一条都不执行!

16、          注意Transaction实例与conn对象的联系——trans=conn.BeginTransaction();

17、          Inventory.cs文件:对某个Item的库存数量进行查询和更改,其中更改主要指根据订单的发货量进行减少

18、          CurrentQtyInStock()方法没有使用Hashtable缓存SQL语句的变量

19、          TakeStock()方法,传入的参数是一个LineItemInfo[]数组,其中包含了某张订单中用户购买的所有物品。既然包括了不同的物品(Item),也就相应地有不同的ItemId,每个Item也有对应的购买数量Quantity

20、          实际上,需要为每一个Item(这里的Item指的是LineItemInfo[]数组中的某一个元素!)数量的减少操作定义一个SQL语句,而这里采用的是将对此张订单中每一项需要购买的Item的数量的减少操作定义一个SQL语句,再将根据所有要购买Item定义的SQL语句”“串联起来,中间用分号分隔,然后拿到数据库中去执行!!!

21、          Item.cs文件:主要完成对Item的两个操作

22、          GetItemsByProduct()方法,根据传入的productId,将此Product类别下的所有Item都选出来。注意,返回的结果是一个IList接口的形式,可以根据此接口,使用index值枚举ArrayList中的每个Item

23、          GetItem()方法很简单,就是根据传入的itemid值,返回给调用程序相应的ItemInfo对象

24、          Item.cs文件的两个方法中,没有用到Hashtable缓存

25、          Order.cs文件:

26、          第一个函数Insert()很特殊,值得研究一下代码实现方式。Insert()方法实现的是向数据库中增加一条订单(Order)记录,而增加一条订单记录需要向三个表当中写入数据,一个是Orders表,它存储了这个订单的所有信息;第二个是LineItem表,其中存储了此订单中,用户订购的所有物品(Item)及每种Item的数量;第三个是OrderStatus表,它存储了订单的状态

27、          Insert()方法的整体思路也是逐步构建SQL语句,并采用了与Inventory.cs文件中TakeStock()方法相同的实现机制,将“向LineItem表插入某张订单中用户订购的所有物品SQL语句,及其所需变量构造出来。这里的SQL执行过程(插入)与TakeStock()方法(更新)类似

28、          Insert()方法执行数据库操作时,还提供了“检错”机制。所执行的SQL语句经过特殊的处理(定义了返回@ID@ERR),返回参数两个值,第一个是新插入Orders表的订单的订单ID号,第二个就是在SQL语句执行过程中的错误数量。如果出现错误,则抛出异常!

29、          第二个GetOrder()方法比较简单,主要是根据传入的Order号,返回一个OrderInfo对象

30、          Product.cs文件:实现两个功能,一是根据给定的Category,将此Category下所有的Product返回,形式为一个IList接口(ArrayList对象的引用?);第二个是一个具备“搜索”功能的方法,根据传入的关键字数组,返回符合条件的Product ArrayList 接口IList

31、          GetProductsBySearch()方法,根据用户提供的输入字符串(数组),返回给调用程序一个满足要求的ArrayList

32、          注意:GetProductsBySearch()方法使用了一个小技巧,拼接了包含查询条件的SQL语句。在自己的项目中可以参考使用

33、          Profile.cs文件:根据最感兴趣的Category的内容,返回一个BannerPath字符串

 

三、 启发:

1、              IDAL层和DAL层中定义的所有方法,都是为了支持“BLL层的需要的!!!都是为了实现“BLL层的逻辑对数据库进行操作的需要而建立的!!!

2、              一个数据库表对应一个Model” 对应一个IDAL” 对应一个SQLServerDAL”

3、              软件开发过程的问题:是否应先进行数据库建模,然后?有网友说是先规划Model,然后设计数据库

4、              由于对特定数据库表进行操作的(增、删、改、查)SQL语句基本格式都是固定的,而针对不同的条目(情况),只有个别的参数不同。所以在针对每个数据库表编制的DAL层的类当中(如Account数据库表对应的Account类),编写好了针对当前数据库表进行增删改查的SQL语句(模板)。模版当中预留了变量的位置,用于处理不同的操作实例的条目,适应所有的情况。当然,对当前数据库表没有涉及到的操作,可以不进行定义!SQL语句模板也要包括所有特定功能的增删改查操作!!!

5、              捋清了从“BLL层调用——具体数据库操作的整个设计和实现过程

6、              强调注意:在DAL层也是要分层的!!!直接操作ADO.NET组件,对数据库进行增删改查的SQLHelper类(DAAB),又单独被抽象出一小层,这样解决了High Level 接口的问题!!!以上知识可以参考MSDN WebCast Modern C#的第8

7、              由于第一遍看PetShop,所以重点看的是系统结构和设计思路。实现具体功能的代码部分也做了简单的研究,但是对于“为什么使用这种方法实现”等问题并没有搞清楚!这要等到自己动手做Demo系统的时候再仔细地分析

 

四、 问题:

1、              private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());与直接private static Hashtable parmCache = new Hashtable());有何区别?也就是说对Hashtable进行同步的意义是什么?

2、              SQLHelper.cs中的Hashtable parmCache的缓存范围是什么?

3、              为什么只有Account类中的SQL语句模板的SqlParameter[]变量数组要缓存在Hashtable中,而Inventory类的却不缓存呢?

4、              多条SQL语句,中间使用分号分隔,然后一起向数据库执行,是否能成功?(为此,准备在本机数据库中做试验!!!结果:可以执行成功!!!)

5、              Hashtable的问题:在TakeStock()方法中,SQLHelper类的Hashtable的作用是什么?由于没有使用SQLHelper类对数据库进行操作,而直接实例化了SqlCommand对象,所以就不涉及到必须使用SqlParameter[]数组的问题!

6、              还有,TakeStock()方法在执行数据库更新的时候,为什么不使用SQLHelper方法了?这完全可以应用啊!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值