进销存
?花了點時間完成了一個進銷存的項目,個人覺得對邏輯分析,架構(gòu)思想都有一定的體會,故拿出來和大家分享下,首先介紹下項目的功能吧,主要功能有采購管理,銷售管理,庫存管理,人員信息管理,系統(tǒng)管理等,不過寫這篇博客的主要目的并不是講解如何實現(xiàn)項目功能,而是分享下該項目的架構(gòu)思想、實現(xiàn)步驟和碰到的一些問題,分享下心得體會罷了......
?
????數(shù)據(jù)庫設(shè)計
?
?
?? 下面進入主題,首先貼上項目的主界面,由于對界面要求不是很高,所以界面相對來說比較簡單,甚至可是說是簡陋了,,呵呵,不過重點不在界面上,勇敢的直接上圖:
?
架構(gòu):?
首先說說項目架構(gòu)吧,,貼上項目模塊圖:
從圖中可知,項目總共分10個模塊,采用三層架構(gòu)+WCF+反射+抽象工廠來搭建,其中還加入了單例模式,緩存機制。下面分別說說每個模塊的作用:
Insigma.PSI.UI:WinForm界面層
Insigma.PSI.Model:模型層,數(shù)據(jù)實體? ? Insigma.PSI.IBLLService:業(yè)務(wù)邏輯接口層,是定義邏輯層的契約層 Insigma.PSI.BLLService:業(yè)務(wù)邏輯實現(xiàn)層,是對接口的實現(xiàn) Insigma.PSI.IDAL:數(shù)據(jù)訪問接口層,是定義訪問層的契約層 Insigma.PSI.SqlServerDAL:數(shù)據(jù)訪問實現(xiàn)層,實現(xiàn)訪問接口層,主要是針對SQL數(shù)據(jù)庫 Insigma.PSI.OracleDAL:數(shù)據(jù)訪問實現(xiàn)層,實現(xiàn)訪問接口層,主要是針對Oracle數(shù)據(jù)庫?? Insigma.PSI.Utility:工具層,主要存放了Oracle數(shù)據(jù)庫,SQL數(shù)據(jù)庫的數(shù)據(jù)庫操作類Insigma.PSI.DBFactory:抽象工廠層,主要為考慮可以使項目可以適用Oracle數(shù)據(jù)庫和SQL數(shù)據(jù)庫,就搭建了一個抽象工廠層,分別在Oracle數(shù)據(jù)庫層和SQL數(shù)據(jù)庫層建立一個 工 廠來實現(xiàn)該抽象工廠
C:\..\WcfWebRelease\:web層,主要用來發(fā)布WCF服務(wù)
?
從圖中可知,庫存模塊主要實現(xiàn)四個模塊的功能,即 庫存列表、出庫/入庫、庫存明細、庫存警報?首先看看庫存列表,上圖:
?
庫存列表的功能比較簡單,只是實現(xiàn)了倉庫的增、刪、改、查,由于功能比較簡單,也就不多做講解了....
?
再貼上出庫/入庫模塊圖:
?
這塊應(yīng)該算是庫存模塊中的核心模塊了,因為該塊的業(yè)務(wù)邏輯比較多,比較繁瑣,大致講講業(yè)務(wù)邏輯吧,大致的邏輯為:出庫單/出庫單-->填寫訂單-->出庫/入庫-->修改庫存信息,按照這個順序來完成入庫出庫,順序不能顛倒,同時還要實現(xiàn)訂單的刪除,修改,在修改庫存信息時由于表和表之間有很多的外鍵關(guān)系,所以要同時刪除多張表中含有刪除信息的內(nèi)容,實現(xiàn)聯(lián)級刪除,由于這里考慮到要保證結(jié)果的一致性,所以用事務(wù)來實現(xiàn)。再看看界面,為了保證用戶按照這個邏輯順序操作,首先我添加了一對單選框(出庫單,入庫單),當(dāng)單選框都沒有選中時,保存訂單按鈕、出庫、入庫按鈕都是不可用狀態(tài),當(dāng)用戶選擇了訂單類型之后,保存訂單按鈕轉(zhuǎn)為可用狀態(tài),需要用戶填寫訂單信息,填寫好對應(yīng)信息之后保存訂單,保存成功之后列表框中出現(xiàn)剛生產(chǎn)的訂單,同時訂單號是自動來生成的,入庫單是“S_I”開頭,出庫單是"S_O"開頭,后面五位數(shù)字為隨機生成,這樣生成的訂單號易于區(qū)別,也避免了訂單號的重復(fù),然后根據(jù)用戶選擇的訂單類型,對應(yīng)的按鈕轉(zhuǎn)為可用(出庫單-->出庫按鈕) ,這樣就保證了用戶始終是按照這個順序來操作,同時訂單列表框下有刪除訂單按鈕,點擊可以刪除選中按鈕。
?
下面那出庫為例,看看如何實現(xiàn)入庫:
點擊【入庫】按鈕,彈出商品選擇窗口,窗口中顯示了訂單號和倉庫編號,同時還有一個【選擇】按鈕,通過該按鈕選擇商品?
?
點擊【選擇】按鈕,彈出商品列表窗口,由于我這里商品記錄比較少,只有兩條,我們就選第二條吧,點擊【確定】按鈕?
?
這時的"入庫信息"窗口中就填寫上了剛才選擇商品的信息,然后只要在填寫上入庫數(shù)量,點擊【確定】就完成了入庫操作了,如圖:
?出庫的思路和入庫一樣,也是先選擇出庫單,然后填寫出庫單信息并保存訂單,然后再給訂單上添加商品,過程也是通過選擇實現(xiàn),由于類同,就不贅述了...
?
?然后是庫存明細模塊,上圖:
?
該模塊主要實現(xiàn)的功能是對存放在各個倉庫中的商品進行清點,點擊商品的行頭就顯示出該商品的信息:編號、數(shù)量、盤點日期、存放倉庫;填寫好盤點的數(shù)量之后單擊【保存】按鈕,實現(xiàn)保存盤點數(shù)據(jù),這個模塊也沒什么難點,唯一復(fù)雜點的就是因為同樣的貨品可以存放到不同的倉庫中,所以點擊時要搜索出該商品所在的所有倉庫編號,并在“存放倉庫”列表中顯示。
?
最后是庫存警報模塊,上圖:
?
?該模塊主要來設(shè)置庫存上限和庫存下限,實現(xiàn)當(dāng)庫存中存放的商品的數(shù)量超過庫存上限或者低于庫存下限時,彈出警告框提醒。
?這樣,我們就簡單的把項目的功能敘述了下,當(dāng)然還有一些細節(jié)的功能,這里就不再羅列了.....
?
代碼:
由于代碼端模塊較多,我們就按照程序執(zhí)行調(diào)用的層次關(guān)系來羅列.這樣相對來說看起來思路比較清晰......Model層只是定義了需要用到的實體而已,不再贅述了.....
1>.Insigma.PSI.IBLLService層
?
?可以看到有很多的功能類,無法全部講解,所以就挑選一塊,后面的模塊層中也著重講解挑選的這一塊,我挑選了庫存管理模塊,即IStoreManageBLLService,貼上該類的代碼:
?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?????????//修改商品數(shù)量
39?????????bool?UpdateGoodNum(StoreDetailsModel?storeDetail);
40?????}
41?}
由于我們要用到WCF來發(fā)布服務(wù),所以這里的每個方法都添加了WCF特性,主要功能是獲取倉庫、獲取倉庫編號、對倉庫的增、刪、改、查;由于出庫入庫對商品的數(shù)量有影響,又由于不存在同一張表格中,所以我們專門定義了一個方法來實現(xiàn)修改商品數(shù)量;然后出庫入庫對應(yīng)一張庫存明細表,執(zhí)行操作之后要修改該表,記錄信息,同時也可以獲取該表信息,定義的方法就那么多了.....
?
2>Insigma.PSI.BLLService層
?
這層是對上面提及的接口層的實現(xiàn),但除了實現(xiàn)之外,我還在這里加了一個反射機制,在這層按照原來三層的思路是要調(diào)用DAL層來實現(xiàn)對數(shù)據(jù)庫的操作,但因為考慮到要適用于不同的數(shù)據(jù)庫,所以我們不知道要調(diào)用哪個數(shù)據(jù)庫層的DAL來操作,這就是這個反射存在的意義了,我們可以通過反射來讀取配置文件中定義的數(shù)據(jù)庫信息,從而創(chuàng)建對應(yīng)數(shù)據(jù)庫類的實例來操作....先貼上StoreManageBLLService的代碼,之后再接著講解,看到了代碼思路會清晰點:?
??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?????????//通過反射獲取對應(yīng)的抽象產(chǎn)品
?11?????????private?IStoreManageDAL?Ismd?=?Refection.GetFactory().StoreManageProduct;
?12?
?13?????????///?<summary>
?14?????????///?獲取StoresHost表數(shù)據(jù)
?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?????????///?修改商品明細的數(shù)量信息
?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?????????///?修改庫存明細的盤點數(shù)量
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的實例的,然后再調(diào)用該實例的方法,那么反射里是怎么實現(xiàn)的呢?貼上代碼:
?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?????????//獲取配置文件中定義的數(shù)據(jù)庫信息
13?????????private?static?string?path?=?ConfigurationManager.AppSettings["DllName"];
14?????????private?static?string?className?=?ConfigurationManager.AppSettings["ClassName"];
15?
16?????????//單例模式-----因為每次加載該程序集都會去調(diào)用相同的DAL?
17?????????//?????????????如果已經(jīng)加載過了?就不要再次加載?提高性能
18?????????static?Refection()
19?????????{?
20?????????????//反射----因為不確定要獲取什么類型的DAL?不知道是Oracle還是SQL等等?所以這里添加一個反射機制
21?????????????string?_classname?=?path?+?"."?+?className;
22????????????DataAccess?=?(AbstractFactory)Assembly.Load(path).CreateInstance(_classname);
23?????????}
24?
25?????????//獲取對應(yīng)數(shù)據(jù)庫的具體工廠
26?????????public?static?AbstractFactory?GetFactory()
27?????????{
28?????????????return?DataAccess;
29?????????}
30?????}
31?}
從代碼可知,我們獲取了配置文件中定義的程序集以及數(shù)據(jù)庫類的信息,通過加載該程序集來獲取該數(shù)據(jù)庫類的實例,同時,添加了單例模式,因為考慮到每次加載該類庫的時候都要來獲取一次數(shù)據(jù)庫類的實例,但是該數(shù)據(jù)庫類只要配置文件定義不變他就不會變,所以不用每次都去創(chuàng)建實例 ,只需要創(chuàng)建一次就可以了,提高性能,所以就是單例模式的作用了,這里首先定義了一個AbstractFactory類型(后面會講到)變量來接受創(chuàng)建好的實例,該變量也是static類型的,保證唯一性,我這里是將構(gòu)造函數(shù)改為static的方式,然后在靜態(tài)構(gòu)造函數(shù)中實例化數(shù)據(jù)庫類,并賦值給定義好的變量,因為靜態(tài)構(gòu)造函數(shù)只會執(zhí)行一次,之后就不會執(zhí)行了,這就保證了只實例一次,然后定義一個GetFactory()方法來返回數(shù)據(jù)庫實例,這樣就達到了"單例"的效果了,當(dāng)然單例模式還有一種思路是將構(gòu)造函數(shù)設(shè)為private,也同樣定義一個靜態(tài)變量和靜態(tài)方法來創(chuàng)建實例,同樣保證了"單例"。
然后看看配置文件中定義的數(shù)據(jù)庫信息:
2???<!--定義數(shù)據(jù)庫信息-->
3???<appSettings>
4?????<!--程序集名稱-->
5?????<add?key="DLLName"?value="Insigma.PSI.OracleDAL"/>
6?????<!--數(shù)據(jù)庫類名-->
7?????<add?key="ClassName"?value="OracleFactory"/>
8???</appSettings>
可以看到配置文件中定義了程序集的名稱,數(shù)據(jù)庫類的名稱,但其實這個數(shù)據(jù)庫類就是工廠類的名稱。反射中提到了AbstractFactory類型,這是抽象工廠模塊中的內(nèi)容,那么為什么要有這個抽象工廠呢??存在的意義是什么呢?我們就來看看抽象工廠,我的思路:定義一個抽象工廠,里面是一些抽象產(chǎn)品,對應(yīng)于IDAL中定義的類型的產(chǎn)品,然后在每個數(shù)據(jù)庫類庫中定義一個具體工廠,該具體工廠繼承抽象工廠,重寫抽象產(chǎn)品,返回具體產(chǎn)品,即對IDAL接口類的實現(xiàn)類(DAL)的對應(yīng)實例,那你會想到了,如沒有工廠我們照樣可以實現(xiàn)用反射類獲取實例的呀,但你想想這時候獲取到得實例是什么?它就是我們工廠類中的單個產(chǎn)品而已,當(dāng)我們的產(chǎn)品有很多的時候怎么辦呢,一個DAL類庫中的每個類都是一個產(chǎn)品,那難道我們把每個產(chǎn)品都在配置文件中去定義,然后用到的時候通過反射去獲取么??顯然不可能,所以我們加了抽象工廠模式了,在DAL類庫中有一個具體的工廠類,我們所有的產(chǎn)品都由該工廠來創(chuàng)建,那我們獲取的是時候只需要獲取工廠實例,然后通過該實例來創(chuàng)建我們需要的產(chǎn)品就可以了......?
?
3>Insigma.PSI.IDAL層
?
同樣的拿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?}
這也是一個接口類,接口的作用就是規(guī)范行為,定義一種契約,繼承該接口的類都必須實現(xiàn)契約,所以這里主要來約束DAL實現(xiàn)層的行為
4>.Insigma.PSI.DBFactory?
?
抽象工廠模塊中就一個抽象工廠類,就直接貼上類代碼:
?2?
?3?namespace?Insigma.PSI.DBFactory
?4?{
?5?????//定義一個抽象工廠?便于適用于不同的數(shù)據(jù)庫??每個數(shù)據(jù)庫都可以建立一個具體工廠?繼承該工廠?
?6?????public?abstract?class?AbstractFactory
?7?????{
?8????????//抽象產(chǎn)品類---對應(yīng)于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中定義的類型都對應(yīng)的建立了一個屬性(也可以定義成方法),因為加了抽象工廠之后,IDAL中的每個類都是一個抽象產(chǎn)品類,是產(chǎn)品類的基類,而DAL中的每個類都是該基類的派生類,都實現(xiàn)了基類中定義的方法,最終返回的具體產(chǎn)品的類型都為抽象產(chǎn)品類型(子類賦值給基類)。
?
5>.Insigma.PSI.OracleDAL
??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?????????//具體產(chǎn)品:SysUserDAL
?22?????????public?override?ISysUserDAL?SysUserProduct
?23?????????{
?24?????????????get?
?25?????????????{
?26?????????????????//首先搜索緩存?看看是否有對應(yīng)的產(chǎn)品
?27?????????????????if?(HttpRuntime.Cache.Get("sysuserdal")?==?null)
?28?????????????????{
?29?????????????????????sud?=?new?SysUserDAL();
?30?????????????????????//添加緩存機制-----將sud添加到緩存?因為每個用戶調(diào)用都會去實例化同一個對象?加入緩存機制?
?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?????????//具體產(chǎn)品:DepartmentDAL
?41?????????public?override?IDepartmentDAL?DepartmentProduct
?42?????????{
?43?????????????get
?44?????????????{
?45?????????????????//首先搜索緩存?看看是否有對應(yīng)的產(chǎn)品
?46?????????????????if?(HttpRuntime.Cache.Get("departmentdal")?==?null)
?47?????????????????{
?48?????????????????????dp?=?new?DepartmentDAL();
?49?????????????????????//添加緩存機制-----將sud添加到緩存?因為每個用戶調(diào)用都會去實例化同一個對象?加入緩存機制?
?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?????????//具體產(chǎn)品:StoreManageDAL
?61?????????public?override?IStoreManageDAL?StoreManageProduct
?62?????????{
?63?????????????get?
?64?????????????{
?65?????????????????//首先搜索緩存?看看是否有對應(yīng)的產(chǎn)品
?66?????????????????if?(HttpRuntime.Cache.Get("storemanagedal")?==?null)
?67?????????????????{
?68?????????????????????sm?=?new?StoreManageDAL();
?69?????????????????????//添加緩存機制-----將sud添加到緩存?因為每個用戶調(diào)用都會去實例化同一個對象?加入緩存機制?
?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?????????//具體產(chǎn)品: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?????????//具體產(chǎn)品: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?????????//具體產(chǎn)品: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?????????//具體產(chǎn)品: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?????????//具體產(chǎn)品: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?}
在創(chuàng)建具體產(chǎn)品實例的時候我們還用到了緩存機制,每次使用產(chǎn)品功能的時候都回去實例化一個具體的產(chǎn)品返回,所以多次使用同一產(chǎn)品的時候就做了很多無謂的實例化,所以我加了一層緩存,用來將產(chǎn)品的實例緩存起來,下次再需要該產(chǎn)品時直接從緩存中讀取就可以了,提高了性能。
我這里用的是Runtime.Cache.Get()來獲取存,Runtime.Cache.Insert()來添加緩存。
當(dāng)然還有一種方法是用HttpContext.Current.Cache.Get()來取,HttpContext.Current.Cache.Insert()來添加緩存。
至于這兩者的區(qū)別,要涉及到asp.net生命周期和其他方面的一些內(nèi)容了,這里就不解析了.....?
?
SqlDAL中的內(nèi)容和Oracle類似,也是建立了一個工廠創(chuàng)建具體產(chǎn)品,同樣繼承并實現(xiàn)了IDAL中定義的方法,這里也不羅列了......?
?
到這里抽象工廠的角色都出現(xiàn)了,那么來總結(jié)下:
抽象工廠:AbstractFactory類
抽象產(chǎn)品:IDAL類庫中每個類
具體工廠:1.OracleFactory? 2.SqlFactory
具體產(chǎn)品:DAL層中定義的每個類?
?
6>.WCF
我們?nèi)匀荒肧toreManageBLL.svc來講解,貼上代碼:
<%@?ServiceHost?Language="C#"?Debug="true"?Service="Insigma.PSI.BLL.StoreManageBLLService"?%>?定義了程序集的名稱和服務(wù)類名,然后在web.config中配置服信息,上代碼:
<system.web>????<compilation?debug="true"?targetFramework="4.0"?/>
??</system.web>
??<system.serviceModel>
????<behaviors>
??????<serviceBehaviors>
????????<behavior>
??????????<!--?為避免泄漏元數(shù)據(jù)信息,請在部署前將以下值設(shè)置為?false?并刪除上面的元數(shù)據(jù)終結(jié)點?-->
??????????<serviceMetadata?httpGetEnabled="true"/>
??????????<!--?要接收故障異常詳細信息以進行調(diào)試,請將以下值設(shè)置為?true。在部署前設(shè)置為?false?以避免泄漏異常信息?-->
??????????<serviceDebug?includeExceptionDetailInFaults="true"/>
????????</behavior>
??????</serviceBehaviors>
????</behaviors>
????<serviceHostingEnvironment?multipleSiteBindingsEnabled="true"?/>
??</system.serviceModel>
??<system.webServer>
????<modules?runAllManagedModulesForAllRequests="true"/>
??</system.webServer>
?
7>.Insigma.PSI.UI?
?
??
服務(wù)配置好了,那我們客戶端怎么調(diào)用呢??所以我們需要在客戶端的app.config配置文件中添加終結(jié)點信息,上代碼:
?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>??
同時,我在客戶端專門定義了一個類用來創(chuàng)建wcf代理,返回BLL實例,上代碼:
??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層沒什么好講的,就是兩個數(shù)據(jù)庫操作類,一個Oracle類,一個SQL類,這里就不貼圖貼代碼了....?
??
疑問解答?
架構(gòu)、項目、代碼端都講解完成了....接下來和大家分享項目中碰到的一個綁定的問題....
首先貼上要綁定的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?}
講講要求吧,就是希望當(dāng)頁面載入是顯示訂單表_商品詳細表的綜合信息,由于是不同的表,所以我在Model層建立了一個單獨的Model類,里面是一對外鍵對象,因為存在主外鍵的關(guān)系,所以我就考慮到了用外鍵對象來存放數(shù)據(jù),然后通過外鍵建立兩張表的視圖,然后獲取視圖數(shù)據(jù),OK,獲取完全沒有問題,獲取到了就是頁面端的綁定了,按照原來的思路,上代碼:
1?????????????//【錯誤】綁定2?????????????List<Handles_GoodDetailsModel>?hand_goodList?=?GetServiceFromWcf.GetHandle_GoodDetails().GetHandle_GoodDetails(sqlWhere);
3?????????????dgv_DetailShow.DataSource?=?hand_goodList;
?結(jié)果就是,始終綁不上,經(jīng)過深思熟慮之后,才覺得應(yīng)該是外界對象的問題,所以收集資料,終于發(fā)現(xiàn)錯誤點確實在外鍵對象上,外鍵對象無法直接直接綁定上去,至少DataGridView無法直接綁定,web中的Eval()、Bind()可以綁定外鍵對象(經(jīng)測試)........好了,問題找到了就要開始解決了,最后終于發(fā)現(xiàn)了一種手動綁定的方法,上代碼:
?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?????????????????//新增一行,該值會隨著循環(huán)綁定自增
?8?????????????????int?i?=?dgv_DetailShow.Rows.Add();
?9?
10?????????????????//給對應(yīng)行綁定數(shù)據(jù)
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?????????}
總結(jié)
- 上一篇: plc系统和工控机的区别
- 下一篇: 手机当电脑音响_电脑音响有杂音怎么办?