分享一個進銷存項目(多層架構)


    花了點時間完成了一個進銷存的項目,個人覺得對邏輯分析,架構思想都有一定的體會,故拿出來和大家分享下,首先介紹下項目的功能吧,主要功能有采購管理,銷售管理,庫存管理,人員信息管理,系統管理等,不過寫這篇博客的主要目的並不是講解如何實現項目功能,而是分享下該項目的架構思想、實現步驟和碰到的一些問題,分享下心得體會罷了......

 

    數據庫設計

 

 

   下面進入主題,首先貼上項目的主界面,由於對界面要求不是很高,所以界面相對來說比較簡單,甚至可是說是簡陋了,,呵呵,不過重點不在界面上,勇敢的直接上圖:

 

架構:

首先說說項目架構吧,,貼上項目模塊圖:

從圖中可知,項目總共分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         }

 

 至此,,本篇博客就算告一個段落了,歡迎大家評點指導。。。。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM