好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

多层架构下的一个进销存项目

多层架构下的一个进销存项目

花了点时间完成了一个进销存的项目,个人觉得对逻辑分析,架构思想都有一定的体会,故拿出来和大家分享下,首先介绍下项目的功能吧,主要功能有采购管理,销售管理,库存管理,人员信息管理,系统管理等,不过写这篇博客的主要目的并不是讲解如何实现项目功能,而是分享下该项目的架构思想、实现步骤和碰到的一些问题,分享下心得体会罢了......

   下面直接开始进入主题,首先贴上项目的主界面,由于对界面要求不是很高,所以界面相对来说比较简单,甚至可是说是简陋了,,呵呵,不过重点不在界面上,勇敢的直接上图:

 

架构: 

首先说说项目架构吧,,贴上项目模块图:

从图中可知,项目总共分10个模块,采用 三层架构+WCF+反射+抽象工厂 来搭建,其中还加入了 单例模式 , 缓存机制 。下面分别说说每个模块的作用:

Insigma.PSI.UI: WinForm界面层

Insigma.PSI.Model: 模型层,数据实体   

Insigma.PSI.IBLLService: 业务逻辑接口层,是定义逻辑层的契约层

Insigma.PSI.BLLService: 业务逻辑实现层,是对接口的实现

Insigma.PSI.IDAL: 数据访问接口层,是定义访问层的契约层

Insigma.PSI.SqlServerDAL: 数据访问实现层,实现访问接口层,主要是针对SQL数据库

Insigma.PSI.OracleDAL: 数据访问实现层,实现访问接口层,主要是针对Oracle数据库  

Insigma.PSI.Utility: 工具层,主要存放了Oracle数据库,SQL数据库的数据库操作类

Insigma.PSI.DBFactory: 抽象工厂层,主要为考虑可以使项目可以适用Oracle数据库和SQL数据库,就搭建了一个抽象工厂层,分别在Oracle数据库层和SQL数据库层建立一个 工 厂来实现该抽象工厂

C:\..\WcfWebRelease\: web层,主要用来发布WCF服务

项目: 

 简单的分析完了框架的每个模块的作用,然后讲讲项目,由于篇幅问题,无法讲解项目的所有功能,所以在这里就拿出一个模块来讲解下,我选择了库存模块

 

从图中可知,库存模块主要实现四个模块的功能,即 库存列表、出库/入库、库存明细、库存警报 

首先看看 库存列表 ,上图:

 

库存列表的功能比较简单,只是实现了仓库的增、删、改、查,由于功能比较简单,也就不多做讲解了....

再贴上 出库/入库 模块图:


 

这块应该算是库存模块中的核心模块了,因为该块的业务逻辑比较多,比较繁琐,大致讲讲业务逻辑吧,大致的逻辑为:出库单/出库单-->填写订单-->出库/入库-->修改库存信息,按照这个顺序来完成入库出库,顺序不能颠倒,同时还要实现订单的删除,修改,在修改库存信息时由于表和表之间有很多的外键关系,所以要同时删除多张表中含有删除信息的内容,实现联级删除,由于这里考虑到要保证结果的一致性,所以用事务来实现。再看看界面,为了保证用户按照这个逻辑顺序操作,首先我添加了一对单选框(出库单,入库单),当单选框都没有选中时,保存订单按钮、出库、入库按钮都是不可用状态,当用户选择了订单类型之后,保存订单按钮转为可用状态,需要用户填写订单信息,填写好对应信息之后保存订单,保存成功之后列表框中出现刚生产的订单,同时订单号是自动来生成的,入库单是“S_I”开头,出库单是"S_O"开头,后面五位数字为随机生成,这样生成的订单号易于区别,也避免了订单号的重复,然后根据用户选择的订单类型,对应的按钮转为可用(出库单-->出库按钮) ,这样就保证了用户始终是按照这个顺序来操作,同时订单列表框下有删除订单按钮,点击可以删除选中按钮。

下面那出库为例,看看如何实现 入库:

点击【入库】按钮,弹出商品选择窗口,窗口中显示了订单号和仓库编号,同时还有一个【选择】按钮,通过该按钮选择商品 

 

点击【选择】按钮,弹出商品列表窗口,由于我这里商品记录比较少,只有两条,我们就选第二条吧,点击【确定】按钮 

 

这时的 "入库信息" 窗口中就填写上了刚才选择商品的信息,然后只要在填写上入库数量,点击【确定】就完成了入库操作了,如图:

 出库的思路和入库一样,也是先选择出库单,然后填写出库单信息并保存订单,然后再给订单上添加商品,过程也是通过选择实现,由于类同,就不赘述了...

 然后是 库存明细 模块,上图:

 

该模块主要实现的功能是对存放在各个仓库中的商品进行清点,点击商品的行头就显示出该商品的信息:编号、数量、盘点日期、存放仓库;填写好盘点的数量之后单击【保存】按钮,实现保存盘点数据,这个模块也没什么难点,唯一复杂点的就是因为同样的货品可以存放到不同的仓库中,所以点击时要搜索出该商品所在的所有仓库编号,并在“存放仓库”列表中显示。

最后是 库存警报 模块,上图:

 

 该模块主要来设置库存上限和库存下限,实现当库存中存放的商品的数量超过库存上限或者低于库存下限时,弹出警告框提醒。

 这样,我们就简单的把项目的功能叙述了下,当然还有一些细节的功能,这里就不再罗列了.....

代码:

由于代码端模块较多,我们就按照程序执行调用的层次关系来罗列.这样相对来说看起来思路比较清晰...... Model层 只是定义了需要用到的实体而已,不再赘述了.....

1>. Insigma.PSI. IBLLService层

 

 可以看到有很多的功能类,无法全部讲解,所以就挑选一块,后面的模块层中也着重讲解挑选的这一块,我挑选了库存管理模块,即 IStoreManageBLLService ,贴上该类的代码:

IStoreManageBLLService


 1   using  Insigma.PSI.Model;
 2   using  System.ServiceModel;
 3  
 4   namespace  Insigma.PSI.IBLLService
 5  {
 6      [ServiceContract]
 7       public   interface  IStoreManageBLLService
 8      {
 9          [OperationContract]
10           // 获取所有仓库
11          List<StoreHouse> GetStores( string  sqlWhere);
12  
13          [OperationContract]
14           // 获取所有仓库编号
15          List< string > GetAllStoreCode();
16  
17          [OperationContract]
18           // 添加仓库
19           bool  AddStore(StoreHouse store);
20  
21          [OperationContract]
22           // 修改仓库
23           bool  UpdateStore(StoreHouse store);
24  
25          [OperationContract]
26           // 删除仓库
27           bool  DeleteStore( string  code);
28  
29          [OperationContract]
30           // 修改库存明细
31           bool  UpdateStoreDetails(GoodsDetailsModel goodDetail);
32  
33          [OperationContract]
34           // 获取商品明细
35          List<StoreDetailsModel> GetStoreDetails( string  sqlWhere);
36  
37          [OperationContract]
38           // 修改商品数量
39           bool  UpdateGoodNum(StoreDetailsModel storeDetail);
40      }
41  }

由于我们要用到WCF来发布服务,所以这里的每个方法都添加了WCF特性,主要功能是获取仓库、获取仓库编号、对仓库的增、删、改、查;由于出库入库对商品的数量有影响,又由于不存在同一张表格中,所以我们专门定义了一个方法来实现修改商品数量;然后出库入库对应一张库存明细表,执行操作之后要修改该表,记录信息,同时也可以获取该表信息,定义的方法就那么多了.....

2> Insigma.PSI .BLLService 层

 

这层是对上面提及的接口层的实现,但除了实现之外,我还在这里加了一个反射机制,在这层按照原来三层的思路是要调用DAL层来实现对数据库的操作,但因为考虑到要适用于不同的数据库,所以我们不知道要调用哪个数据库层的DAL来操作,这就是这个反射存在的意义了,我们可以通过反射来读取配置文件中定义的数据库信息,从而创建对应数据库类的实例来操作....先贴上 StoreManageBLLService 的代码,之后再接着讲解,看到了代码思路会清晰点: 

StoreManageBLLService

1   using  Insigma.PSI.Model;
  2   using  Insigma.PSI.IBLLService;
  3   using  Insigma.PSI.IDAL;
  4   using  Insigma.PSI.DBFactory;
  5  
  6   namespace  Insigma.PSI.BLL
  7  {
  8       public   class  StoreManageBLLService:IStoreManageBLLService
  9      {
 10           // 通过反射获取对应的抽象产品
 11            private  IStoreManageDAL Ismd = Refection.GetFactory().StoreManageProduct;
 12  
 13           ///   <summary>
 14            ///  获取StoresHost表数据
 15            ///   </summary>
 16            ///   <param name="sqlWhere"></param>
 17            ///   <returns></returns>
 18            public  List<StoreHouse> GetStores( string  sqlWhere)
 19          {
 20               return  Ismd.GetStores(sqlWhere);
 21          }
 22  
 23           ///   <summary>
 24            ///  添加仓库
 25            ///   </summary>
 26            ///   <param name="store"></param>
 27            ///   <returns></returns>
 28            public   bool  AddStore(StoreHouse store)
 29          {
 30               int  result = Ismd.AddStore(store);
 31               if  (result >  0 )
 32              {
 33                   return   true ;
 34              }
 35               else
 36              {
 37                   return   false ;
 38              }
 39          }
 40  
 41           ///   <summary>
 42            ///  修改仓库
 43            ///   </summary>
 44            ///   <param name="store"></param>
 45            ///   <returns></returns>
 46            public   bool  UpdateStore(StoreHouse store)
 47          {
 48               int  result = Ismd.UpdateStore(store);
 49  
 50               if  (result >  0 )
 51              {
 52                   return   true ;
 53              }
 54               else
 55              {
 56                   return   false ;
 57              }
 58          }
 59  
 60           ///   <summary>
 61            ///  删除仓库
 62            ///   </summary>
 63            ///   <param name="code"></param>
 64            ///   <returns></returns>
 65            public   bool  DeleteStore( string  code)
 66          {
 67               int  result = Ismd.DeleteStore(code);
 68  
 69               if  (result >  0 )
 70              {
 71                   return   true ;
 72              }
 73               else
 74              {
 75                   return   false ;
 76              }
 77          }
 78  
 79           ///   <summary>
 80            ///  获取所有仓库编号
 81            ///   </summary>
 82            ///   <returns></returns>
 83            public  List< string > GetAllStoreCode()
 84          {
 85               return  Ismd.GetAllStoreCode();
 86          }
 87  
 88           ///   <summary>
 89            ///  修改商品明细的数量信息
 90            ///   </summary>
 91            ///   <param name="goodDetail"></param>
 92            ///   <returns></returns>
 93            public   bool  UpdateStoreDetails(GoodsDetailsModel goodDetail)
 94          {
 95               int  result = Ismd.UpdateStoreDetails(goodDetail);
 96  
 97               if  (result >  0 )
 98              {
 99                   return   true ;
100              }
101               else
102              {
103                   return   false ;
104              }
105          }
106  
107           ///   <summary>
108            ///  获取所有库存明细
109            ///   </summary>
110            ///   <param name="sqlWhere"></param>
111            ///   <returns></returns>
112            public  List<StoreDetailsModel> GetStoreDetails( string  sqlWhere)
113          {
114               return  Ismd.GetStoreDetails(sqlWhere);
115          }
116  
117           ///   <summary>
118            ///  修改库存明细的盘点数量
119            ///   </summary>
120            ///   <param name="storeDetail"></param>
121            ///   <returns></returns>
122            public   bool  UpdateGoodNum(StoreDetailsModel storeDetail)
123          {
124               int  result = Ismd.UpdateGoodNum(storeDetail);
125  
126               if  (result >  0 )
127              {
128                   return   true ;
129              }
130               else
131              {
132                   return   false ;
133              }
134          }
135      }
136  } 

从代码中可以看到我们是通过反射来获取DAL的实例的,然后再调用该实例的方法,那么反射里是怎么实现的呢?贴上代码:

反射

 1   using  System.Configuration;
 2   using  System.Reflection;
 3   using  Insigma.PSI.DBFactory;
 4  
 5   namespace  Insigma.PSI.BLL
 6  {
 7       public   class  Refection
 8      {
 9           // 定义一个抽象工厂类的对象实例 用于保存作用
10            private   static  AbstractFactory DataAccess =  null ;
11  
12           // 获取配置文件中定义的数据库信息
13            private   static   string  path = ConfigurationManager.AppSettings[ " DllName " ];
14           private   static   string  className = ConfigurationManager.AppSettings[ " ClassName " ];
15  
16           // 单例模式-----因为每次加载该程序集都会去调用相同的DAL 
17            //              如果已经加载过了 就不要再次加载 提高性能
18            static  Refection()
19          { 
20               // 反射----因为不确定要获取什么类型的DAL 不知道是Oracle还是SQL等等 所以这里添加一个反射机制
21                string  _classname = path +  " . "  + className;
22             DataAccess = (AbstractFactory)Assembly.Load(path).CreateInstance(_classname);
23          }
24  
25           // 获取对应数据库的具体工厂
26            public   static  AbstractFactory GetFactory()
27          {
28               return  DataAccess;
29          }
30      }
31  }

从代码可知,我们获取了配置文件中定义的程序集以及数据库类的信息,通过加载该程序集来获取该数据库类的实例,同时,添加了单例模式,因为考虑到每次加载该类库的时候都要来获取一次数据库类的实例,但是该数据库类只要配置文件定义不变他就不会变,所以不用每次都去创建实例 ,只需要创建一次就可以了,提高性能,所以就是单例模式的作用了,这里首先定义了一个AbstractFactory类型(后面会讲到)变量来接受创建好的实例,该变量也是static类型的,保证唯一性,我这里是将构造函数改为static的方式,然后在静态构造函数中实例化数据库类,并赋值给定义好的变量,因为静态构造函数只会执行一次,之后就不会执行了,这就保证了只实例一次,然后定义一个GetFactory()方法来返回数据库实例,这样就达到了"单例"的效果了,当然单例模式还有一种思路是将构造函数设为private,也同样定义一个静态变量和静态方法来创建实例,同样保证了"单例"。

然后看看配置文件中定义的数据库信息:

web.config

1  <configuration>
2    <!--定义数据库信息-->
3    <appSettings>
4      <!--程序集名称-->
5      <add key= " DLLName "  value= " Insigma.PSI.OracleDAL " />
6      <!--数据库类名-->
7      <add key= " ClassName "  value= " OracleFactory " />
8    </appSettings>

可以看到配置文件中定义了程序集的名称,数据库类的名称,但其实这个数据库类就是工厂类的名称。反射中提到了AbstractFactory类型,这是抽象工厂模块中的内容,那么为什么要有这个抽象工厂呢??存在的意义是什么呢?我们就来看看抽象工厂,我的思路:定义一个抽象工厂,里面是一些抽象产品,对应于IDAL中定义的类型的产品,然后在每个数据库类库中定义一个具体工厂,该具体工厂继承抽象工厂,重写抽象产品,返回具体产品,即对IDAL接口类的实现类(DAL)的对应实例,那你会想到了,如没有工厂我们照样可以实现用反射类获取实例的呀,但你想想这时候获取到得实例是什么?它就是我们工厂类中的单个产品而已,当我们的产品有很多的时候怎么办呢,一个DAL类库中的每个类都是一个产品,那难道我们把每个产品都在配置文件中去定义,然后用到的时候通过反射去获取么??显然不可能,所以我们加了抽象工厂模式了,在DAL类库中有一个具体的工厂类,我们所有的产品都由该工厂来创建,那我们获取的是时候只需要获取工厂实例,然后通过该实例来创建我们需要的产品就可以了...... 

3> Insigma.PSI. IDAL层

 

同样的拿IStoreManageDAL类讲解,上代码:

IStoreManageDAL

1   using  Insigma.PSI.Model;
 2  
 3   namespace  Insigma.PSI.IDAL
 4  {
 5       public   interface  IStoreManageDAL
 6      {
 7          List<StoreHouse> GetStores( string  sqlWhere);
 8          List< string > GetAllStoreCode();
 9           int  AddStore(StoreHouse store);
10           int  UpdateStore(StoreHouse store);
11           int  DeleteStore( string  code);
12           int  UpdateStoreDetails(GoodsDetailsModel goodDetail);
13          List<StoreDetailsModel> GetStoreDetails( string  sqlWhere);
14           int  UpdateGoodNum(StoreDetailsModel storeDetail);
15      }
16  }

这也是一个接口类,接口的作用就是规范行为,定义一种契约,继承该接口的类都必须实现契约,所以这里主要来约束DAL实现层的行为

4>. Insigma.PSI.DBFactory  

 

抽象工厂模块中就一个抽象工厂类,就直接贴上类代码:

AbstractFactory

1   using  Insigma.PSI.IDAL;
 2  
 3   namespace  Insigma.PSI.DBFactory
 4  {
 5       // 定义一个抽象工厂 便于适用于不同的数据库  每个数据库都可以建立一个具体工厂 继承该工厂 
 6        public   abstract   class  AbstractFactory
 7      {
 8          // 抽象产品类---对应于IDAL层
 9           public   abstract  ISysUserDAL SysUserProduct {  get ; }
10          public   abstract  IStoreManageDAL StoreManageProduct {  get ;}
11          public   abstract  IDepartmentDAL DepartmentProduct {  get ; }
12          public   abstract  IHandleGeneralsDAL HandleGeneralsProduct {  get ; }
13          public   abstract  IGoodsDAL GoodsProduct {  get ; }
14          public   abstract  IHandle_GoodDetailsDAL Handle_GoodDetailsProduct {  get ; }
15          public   abstract  IStaffsDAL StaffsProduct {  get ; }
16          public   abstract  ICompanyDAL CompanyProduct {  get ; }
17      }
18  }

在抽象类中为每个在IDAL中定义的类型都对应的建立了一个属性(也可以定义成方法),因为加了抽象工厂之后,IDAL中的每个类都是一个抽象产品类,是产品类的基类,而DAL中的每个类都是该基类的派生类,都实现了基类中定义的方法,最终返回的具体产品的类型都为抽象产品类型(子类赋值给基类)。

5>. Insigma.PSI.OracleDAL

  

有一个工厂类,用于创建具体产品实例,贴上工厂类代码:

Oracle工厂

1   using  Insigma.PSI.DBFactory;
  2   using  System.Web;
  3   using  Insigma.PSI.IDAL;
  4  
  5   namespace  Insigma.PSI.OracleDAL
  6  {
  7       // 具体工厂:Oracle
  8        public   class  OracleFactory:AbstractFactory
  9      {
 10           // 定义DAL类型变量,用于保存
 11            private  SysUserDAL sud =  null ;
 12           private  DepartmentDAL dp =  null ;
 13           private  StoreManageDAL sm =  null ;
 14           private  HandleGeneralsDAL hg =  null ;
 15           private  GoodsDAL gd =  null ;
 16           private  Handle_GoodDetailsDAL h_g =  null ;
 17           private  StaffsDAL sd =  null ;
 18           private  CompanyDAL cd =  null ;
 19  
 20  
 21           // 具体产品:SysUserDAL
 22            public   override  ISysUserDAL SysUserProduct
 23          {
 24               get  
 25              {
 26                   // 首先搜索缓存 看看是否有对应的产品
 27                    if  (HttpRuntime.Cache.Get( " sysuserdal " ) ==  null )
 28                  {
 29                      sud =  new  SysUserDAL();
 30                       // 添加缓存机制-----将sud添加到缓存 因为每个用户调用都会去实例化同一个对象 加入缓存机制 
 31                        //                  如果要获取相同类型的对象 则可以直接从缓存中获取 提高性能
 32                       HttpRuntime.Cache.Insert( " sysuserdal " , sud, null ,DateTime.Now.AddMinutes( 5 ),TimeSpan.Zero);
 33                  }
 34                  
 35                   // 返回存储在缓存中的值
 36                    return  (SysUserDAL)HttpRuntime.Cache.Get( " sysuserdal " );
 37              }
 38          }
 39  
 40           // 具体产品:DepartmentDAL
 41            public   override  IDepartmentDAL DepartmentProduct
 42          {
 43               get
 44              {
 45                   // 首先搜索缓存 看看是否有对应的产品
 46                    if  (HttpRuntime.Cache.Get( " departmentdal " ) ==  null )
 47                  {
 48                      dp =  new  DepartmentDAL();
 49                       // 添加缓存机制-----将sud添加到缓存 因为每个用户调用都会去实例化同一个对象 加入缓存机制 
 50                        //                  如果要获取相同类型的对象 则可以直接从缓存中获取 提高性能
 51                       HttpRuntime.Cache.Insert( " departmentdal " , dp,  null , DateTime.Now.AddMinutes( 5 ), TimeSpan.Zero);
 52                  }
 53  
 54                   // 返回存储在缓存中的值
 55                    return  (DepartmentDAL)HttpRuntime.Cache.Get( " departmentdal " );
 56  
 57              }
 58          }
 59  
 60           // 具体产品:StoreManageDAL
 61            public   override  IStoreManageDAL StoreManageProduct
 62          {
 63               get  
 64              {
 65                   // 首先搜索缓存 看看是否有对应的产品
 66                    if  (HttpRuntime.Cache.Get( " storemanagedal " ) ==  null )
 67                  {
 68                      sm =  new  StoreManageDAL();
 69                       // 添加缓存机制-----将sud添加到缓存 因为每个用户调用都会去实例化同一个对象 加入缓存机制 
 70                        //                  如果要获取相同类型的对象 则可以直接从缓存中获取 提高性能
 71                       HttpRuntime.Cache.Insert( " storemanagedal " , sm,  null , DateTime.Now.AddMinutes( 5 ), TimeSpan.Zero);
 72                  }
 73  
 74                   // 返回存储在缓存中的值
 75                    return  (StoreManageDAL)HttpRuntime.Cache.Get( " storemanagedal " );
 76              }
 77          }
 78  
 79           // 具体产品:HandleGeneralsDAL
 80            public   override  IHandleGeneralsDAL HandleGeneralsProduct
 81          {
 82               get  
 83              {
 84                   if (HttpRuntime.Cache.Get( " handlegenerals " )== null )
 85                  {
 86                      hg =  new  HandleGeneralsDAL();
 87                      HttpRuntime.Cache.Insert( " handlegenerals " , hg);
 88                  }
 89                   return  (HandleGeneralsDAL)HttpRuntime.Cache.Get( " handlegenerals " );
 90              }
 91          }
 92  
 93           // 具体产品:GoodsDAL 
 94            public   override  IGoodsDAL GoodsProduct
 95          {
 96               get  
 97              {
 98                   if  (HttpRuntime.Cache.Get( " good " ) ==  null )
 99                  {
100                      gd =  new  GoodsDAL();
101                      HttpRuntime.Cache.Insert( " good " , gd);
102                  }
103                   return  (GoodsDAL)HttpRuntime.Cache.Get( " good " );
104              }
105          }
106  
107           // 具体产品:Handle_GoodDetailsDAL
108            public   override  IHandle_GoodDetailsDAL Handle_GoodDetailsProduct
109          {
110               get
111              {
112                   if  (HttpRuntime.Cache.Get( " hand_good " ) ==  null )
113                  {
114                      h_g =  new  Handle_GoodDetailsDAL();
115                      HttpRuntime.Cache.Insert( " hand_good " , h_g);
116                  }
117                   return  (Handle_GoodDetailsDAL)HttpRuntime.Cache.Get( " hand_good " );
118              }
119          }
120  
121           // 具体产品:StaffsDAL
122            public   override  IStaffsDAL StaffsProduct
123          {
124               get  
125              {
126                   if  (HttpRuntime.Cache.Get( " staff " ) ==  null )
127                  {
128                      sd =  new  StaffsDAL();
129                      HttpRuntime.Cache.Insert( " staff " , sd);
130                  }
131                   return  (StaffsDAL)HttpRuntime.Cache.Get( " staff " );
132              }
133          }
134  
135           // 具体产品:CompanyDAL
136            public   override  ICompanyDAL CompanyProduct
137          {
138               get
139              {
140                   if  (HttpRuntime.Cache.Get( " company " ) ==  null )
141                  {
142                      cd =  new  CompanyDAL();
143                      HttpRuntime.Cache.Insert( " company " , cd);
144                  }
145                   return  (CompanyDAL)HttpRuntime.Cache.Get( " company " );
146              }
147          }
148  
149      }
150  }

在创建具体产品实例的时候我们还用到了 缓存机制 ,每次使用产品功能的时候都回去实例化一个具体的产品返回,所以多次使用同一产品的时候就做了很多无谓的实例化,所以我加了一层缓存,用来将产品的实例缓存起来,下次再需要该产品时直接从缓存中读取就可以了,提高了性能。

我这里用的是 Runtime.Cache.Get() 来获取存, Runtime.Cache.Insert() 来添加缓存。

当然还有一种方法是用 HttpContext.Current.Cache.Get() 来取, HttpContext.Current.Cache.Insert() 来添加缓存。

至于这两者的区别,要涉及到asp.net生命周期和其他方面的一些内容了,这里就不解析了..... 

SqlDAL中的内容和Oracle类似,也是建立了一个工厂创建具体产品,同样继承并实现了IDAL中定义的方法,这里也不罗列了...... 

到这里抽象工厂的角色都出现了,那么来总结下:

抽象工厂: AbstractFactory类

抽象产品: IDAL类库中每个类

具体工厂: 1.OracleFactory  2.SqlFactory

具体产品: DAL层中定义的每个类 

6>.WCF

我们仍然拿StoreManageBLL.svc来讲解,贴上代码:

StoreManageBLLService


<%@ ServiceHost Language= " C# "  Debug= " true "  Service= " Insigma.PSI.BLL.StoreManageBLLService "  %>

 定义了程序集的名称和服务类名,然后在web.config中配置服信息,上代码:

web.config

<system.web>
    <compilation debug= " true "  targetFramework= " 4.0 "  />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为  false  并删除上面的元数据终结点 -->
          <serviceMetadata httpGetEnabled= " true " />
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为  true 。在部署前设置为  false  以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults= " true " />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled= " true "  />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests= " true " />
  </system.webServer>

7>. Insigma.PSI.UI  

服务配置好了,那我们客户端怎么调用呢??所以我们需要在客户端的app.config配置文件中添加终结点信息,上代码:

app.config

 1  <configuration>
 2      <system.serviceModel>
 3          <client>
 4              <endpoint address= " http://localhost:33864/WcfWebRelease/SysUserBLL.svc "
 5                  binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.ISysUserBLLSerivce "
 6                  name= " SysUserService "  />
 7              <endpoint address= " http://localhost:33864/WcfWebRelease/DepartmentBLL.svc "
 8                  binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IDepartmentBLLService "
 9                  name= " DepartmentBLLService "  />
10              <endpoint address= " http://localhost:33864/WcfWebRelease/StoreManageBLL.svc "
11                  binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IStoreManageBLLService "
12                  name= " StoreManageBLLService "  />
13            <endpoint address= " http://localhost:33864/WcfWebRelease/HandleGeneralsBLL.svc "
14                 binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IHandleGeneralsBLLService "
15                 name= " HandleGeneralsBLLService "  />
16            <endpoint address= " http://localhost:33864/WcfWebRelease/GoodsBLL.svc "
17                binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IGoodsBLLService "
18                name= " GoodsBLLService "  />
19            <endpoint address= " http://localhost:33864/WcfWebRelease/Handle_GoodDetails.svc "
20               binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IHandle_GoodDetailsBLLService "
21               name= " Handle_GoodDetailsBLLService "  />
22            <endpoint address= " http://localhost:33864/WcfWebRelease/StaffsBLL.svc "
23               binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.IStaffsBLLService "
24               name= " StaffsBLLService "  />
25            <endpoint address= " http://localhost:33864/WcfWebRelease/CompanyBLL.svc "
26               binding= " basicHttpBinding "  bindingConfiguration= ""  contract= " Insigma.PSI.IBLLService.ICompanyBLLService "
27               name= " CompanyBLLService "  />
28          </client>
29      </system.serviceModel>  

同时,我在客户端专门定义了一个类用来创建wcf代理,返回BLL实例,上代码:

代理类

 1   namespace  Insigma.PSI.UI
  2  {
  3       public   class  GetServiceFromWcf
  4      {
  5  
  6           private   static  ISysUserBLLSerivce _SysUserBLLSerivceProxy;
  7           private   static  IDepartmentBLLService _DepartmentBLLService;
  8           private   static  IStoreManageBLLService _StoreManageBLLService;
  9           private   static  IHandleGeneralsBLLService _HandleGeneralsBLLService;
 10           private   static  IGoodsBLLService _GoodsBLLService;
 11           private   static  IHandle_GoodDetailsBLLService _Handle_GoodDetailsBLLService;
 12           private   static  IStaffsBLLService _StaffsBLLService;
 13           private   static  ICompanyBLLService _CompanyBLLService;
 14  
 15  
 16           // 获取SysUser代理
 17            public   static  ISysUserBLLSerivce GetSysUserBLLSerivceProxy()
 18          {
 19               if  (_SysUserBLLSerivceProxy ==  null )
 20              {
 21                  ChannelFactory<ISysUserBLLSerivce> channelFactory =  new  ChannelFactory<ISysUserBLLSerivce>( " SysUserService " );
 22                  _SysUserBLLSerivceProxy = channelFactory.CreateChannel();
 23              }
 24               return  _SysUserBLLSerivceProxy;
 25          }
 26  
 27           // 获取Department代理
 28            public   static  IDepartmentBLLService GetDepartmentBLLServiceProxy()
 29          {
 30               if  (_DepartmentBLLService ==  null )
 31              {
 32                  ChannelFactory<IDepartmentBLLService> channelFactory =  new  ChannelFactory<IDepartmentBLLService>( " DepartmentBLLService " );
 33                  _DepartmentBLLService = channelFactory.CreateChannel();
 34              }
 35               return  _DepartmentBLLService;
 36          }
 37  
 38           // 获取StoreHost代理
 39            public   static  IStoreManageBLLService GetStoreManageBLLServiceProxy()
 40          {
 41               if  (_StoreManageBLLService ==  null )
 42              {
 43                  ChannelFactory<IStoreManageBLLService> channelFactory =  new  ChannelFactory<IStoreManageBLLService>( " StoreManageBLLService " );
 44                  _StoreManageBLLService = channelFactory.CreateChannel();
 45              }
 46               return  _StoreManageBLLService;
 47          }
 48  
 49           // 获取HandleGenerals代理
 50            public   static  IHandleGeneralsBLLService GetHandleGeneralsBLLServiceProxy()
 51          {
 52               if  (_HandleGeneralsBLLService ==  null )
 53              {
 54                  ChannelFactory<IHandleGeneralsBLLService> channelFactory =  new  ChannelFactory<IHandleGeneralsBLLService>( " HandleGeneralsBLLService " );
 55                  _HandleGeneralsBLLService = channelFactory.CreateChannel();
 56              }
 57               return  _HandleGeneralsBLLService;
 58          }
 59  
 60           // 获取Goods代理
 61            public   static  IGoodsBLLService GetGoodsBLLService()
 62          {
 63               if  (_GoodsBLLService ==  null )
 64              {
 65                  ChannelFactory<IGoodsBLLService> channelFactory =  new  ChannelFactory<IGoodsBLLService>( " GoodsBLLService " );
 66                  _GoodsBLLService = channelFactory.CreateChannel();
 67              }
 68               return  _GoodsBLLService;
 69          }
 70  
 71           // 获取Handle_GoodDetails代理
 72            public   static  IHandle_GoodDetailsBLLService GetHandle_GoodDetails()
 73          {
 74               if  (_Handle_GoodDetailsBLLService ==  null )
 75              {
 76                  ChannelFactory<IHandle_GoodDetailsBLLService> channelFactory =  new  ChannelFactory<IHandle_GoodDetailsBLLService>( " Handle_GoodDetailsBLLService " );
 77                  _Handle_GoodDetailsBLLService = channelFactory.CreateChannel();
 78              }
 79               return  _Handle_GoodDetailsBLLService;
 80          }
 81  
 82           // 获取Staffs代理
 83            public   static  IStaffsBLLService GetStaffsBLLService()
 84          {
 85               if  (_StaffsBLLService ==  null )
 86              {
 87                  ChannelFactory<IStaffsBLLService> channelFactory =  new  ChannelFactory<IStaffsBLLService>( " StaffsBLLService " );
 88                  _StaffsBLLService = channelFactory.CreateChannel();
 89              }
 90               return  _StaffsBLLService;
 91          }
 92  
 93           /// 获取Company代理
 94            public   static  ICompanyBLLService GetCompanyBLLService()
 95          {
 96               if  (_CompanyBLLService ==  null )
 97              {
 98                  ChannelFactory<ICompanyBLLService> channelFactory =  new  ChannelFactory<ICompanyBLLService>( " CompanyBLLService " );
 99                  _CompanyBLLService = channelFactory.CreateChannel();
100              }
101               return  _CompanyBLLService;
102          }
103      }
104  }

Utility 层 没什么好讲的,就是两个数据库操作类,一个Oracle类,一个SQL类,这里就不贴图贴代码了....  

疑问解答  

架构、项目、代码端都讲解完成了....接下来和大家分享项目中碰到的一个绑定的问题....

首先贴上要绑定的Model层信息:

外键对象

 1   namespace  Insigma.PSI.Model
 2  {
 3      [DataContract]
 4       public   class  Handles_GoodDetailsModel
 5      {
 6           // 外键对象
 7           [DataMember]
 8           public  HandelGeneralsModel Handles;
 9  
10          [DataMember]
11           public  GoodsDetailsModel GoodsDetails;
12      }
13  }

讲讲要求吧,就是希望当页面载入是显示订单表_商品详细表的综合信息,由于是不同的表,所以我在Model层建立了一个单独的Model类,里面是一对外键对象,因为存在主外键的关系,所以我就考虑到了用外键对象来存放数据,然后通过外键建立两张表的视图,然后获取视图数据,OK,获取完全没有问题,获取到了就是页面端的绑定了,按照原来的思路,上代码:

错误绑定

1               // 【错误】绑定
2               List<Handles_GoodDetailsModel> hand_goodList = GetServiceFromWcf.GetHandle_GoodDetails().GetHandle_GoodDetails(sqlWhere);
3              dgv_DetailShow.DataSource = hand_goodList;

 结果就是,始终绑不上,经过深思熟虑之后,才觉得应该是外界对象的问题,所以收集资料,终于发现错误点确实在外键对象上,外键对象无法直接直接绑定上去,至少DataGridView无法直接绑定,web中的Eval()、Bind()可以绑定外键对象(经测试)........好了,问题找到了就要开始解决了,最后终于发现了一种手动绑定的方法,上代码:

正确绑定

1               // 【正确】手工绑定
 2               List<Handles_GoodDetailsModel> hand_goodList = GetServiceFromWcf.GetHandle_GoodDetails().GetHandle_GoodDetails(sqlWhere);
 3               // 由于存在外键对象  无法直接绑定 需要手工绑定
 4               dgv_DetailShow.Rows.Clear();
 5               foreach  (Handles_GoodDetailsModel model  in  hand_goodList)
 6              {
 7                   // 新增一行,该值会随着循环绑定自增
 8                    int  i = dgv_DetailShow.Rows.Add();
 9  
10                   // 给对应行绑定数据
11                   dgv_DetailShow.Rows[i].Cells[ " HandCode " ].Value = model.Handles.HandCode;
12                  dgv_DetailShow.Rows[i].Cells[ " ContCode " ].Value = model.Handles.ContCode;
13                  dgv_DetailShow.Rows[i].Cells[ " HandDate " ].Value = model.Handles.HandDate;
14                  dgv_DetailShow.Rows[i].Cells[ " StaffCode " ].Value = model.Handles.StaffCode;
15                  dgv_DetailShow.Rows[i].Cells[ " StoreDate " ].Value = model.Handles.StoreDate;
16  
17                  dgv_DetailShow.Rows[i].Cells[ " DetailCode " ].Value = model.GoodsDetails.DetailCode;
18                  dgv_DetailShow.Rows[i].Cells[ " GooCode " ].Value = model.GoodsDetails.GooCode;
19                  dgv_DetailShow.Rows[i].Cells[ " GooNum " ].Value = model.GoodsDetails.GooNum;
20                  dgv_DetailShow.Rows[i].Cells[ " GooPrice " ].Value = model.GoodsDetails.GooPrice;
21                  dgv_DetailShow.Rows[i].Cells[ " StoreCodeIn " ].Value = model.GoodsDetails.StoreCodeIn;
22                  dgv_DetailShow.Rows[i].Cells[ " StoreCodeOut " ].Value = model.GoodsDetails.StoreCodeOut;
23              }
24          }

 至此,,本篇博客就算告一个段落了,欢迎大家评点指导。。。。。。。

 

分类:  架构思想

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于多层架构下的一个进销存项目的详细内容...

  阅读:44次