引言:本文不是從理論的角度來探討三層架構,而是用一個示例來介紹如何建設一個三層架構的項目,並說明項目中各個文件所處的層次與作用。寫本文的目的,不是為了說明自己的這個方法有多對,別人的肯定不對,而是希望給那些初學三層架構卻不知從何入手的朋友提供一點幫助。因為網上的文章,大多是注重理論的介紹,而忽略了具體的實踐應用,或者有示例但講得不透徹。導致看了之後,理論上又學習了一遍,但還是不知道代碼怎麼寫。所以想從這個方面入手寫一下,讓從來沒做過三層架構的初學者也能照貓畫虎,寫出代碼來。文章表述的是筆者個人對三層架構的認識,肯定有許多不足的地方,歡迎大家指正,小弟也會根據反饋來修改這篇文章。文中的代碼是偽代碼,僅用來闡明思路。
正文:
一提三層架構,大家都知道是表現層(UI),業務邏輯層(BLL)和數據訪問層(DAL),而且每層如何細分也都有很多的方法。但具體代碼怎麼寫,到底那些文件算在哪一層,卻是模模糊糊的。下面用一個簡單的例子來帶領大家實戰三層架構的項目,這個例子只有一個功能,就是用戶的簡單管理。
首先建立一個空白解決方案,添加如下項目及文件
1、添加ASP.NET Web Application項目,命名為UI,新建Web Form類型文件User.aspx(含User.aspx.cs)
2、添加ClassLibrary項目,命名為BLL,新建Class類型文件UserBLL.cs
3、添加ClassLibrary項目,命名為DAL,新建Class類型文件UserDAL.cs。添加SQLHelper引用。(這個是微軟的數據訪問類,也可以不用,直接編寫所有的數據訪問代碼。我一般用自己寫的數據訪問類DataAccessHelper )。
4、添加ClassLibrary項目,命名為Model,新建Class類型文件UserModel.cs
5、添加ClassLibrary項目,命名為IDAL,新建Interface類型文件IUserDAL.cs
6、添加ClassLibrary項目,命名為ClassFactory
相信大家已經看出來了,這個和Petshop的示例沒什麼區別,而且更簡單,因為在下也是通過Petshop學習三層架構的。但一些朋友對於這幾個項目所處的層次,以及它們之間的關系,可能比較模糊,這裡逐個說明一下:
1、User.aspx和User.aspx.cs
這兩個文件(以及文件所屬的項目,下面也是如此,不再重復強調了)都屬於表現層部分。User.aspx比較好理解,因為它就是顯示頁面了。User.aspx.cs有些人覺得不應該算,而是要劃到業務邏輯層中去。如果不做分層的話,那麼讓User.aspx.cs來處理業務邏輯,甚至操作數據庫都沒什麼問題,但是做分層的話,這樣就不應該了。在分層結構中,User.aspx.cs僅應該處理與顯示有關的內容,其它部分都不應該涉及。
舉例:我們實現用列表方式顯示用戶的功能,那麼提取信息的工作是由BLL來做的,UI(本例中是User.aspx.cs)調用BLL得到UserInfo後,通過代碼綁定到User.aspx的數據控件上,就實現了列表的顯示。在此過程中User.aspx.cs對UI沒有起到什麼作用,僅是用來傳遞數據,而且因為實際編碼中大部分情況都是如此的實現,所以使有些人覺得User.aspx.cs不應該算UI,而應該並入BLL負責邏輯處理。繼續往下看,這時提出了一個新需求,要求在每個用戶的前面加一個圖標,生動地表現出用戶的性別,而且不滿18歲的用兒童圖標表示。這個需求的實現,就輪到User.aspx.cs來做了,這種情況下User.aspx.cs才算有了真正的用途。
2、NewBLL.cs
添加如下方法:
public IList<UserInfo> GetUsers():返回所有的用戶信息列表
public UserInfo GetUser(int UserId):返回指定用戶的詳細信息
public bool AddUser(UserInfo User):新增用戶信息
public bool ChangeUser(UserInfo User):更新用戶信息
public void RemoveUser(int UserId):移除用戶信息
此文件就屬於業務邏輯層了,專門用來處理與業務邏輯有關的操作。可能有很多人覺得這一層唯一的用途,就是把表現層傳過來的數據轉發給數據層。這種情況確實很多,但這只能說明項目比較簡單,或者項目本身與業務的關系結合的不緊密(比如當前比較流行的MIS),所以造成業務層無事可做,只起到了一個轉發的作用。但這不代表業務層可有可無,隨著項目的增大,或者業務關系比較多,業務層就會體現出它的作用來了。
此處最可能造成錯誤的,就是把數據操作代碼劃在了業務邏輯層,而把數據庫作為了數據訪問層。
舉例:有些朋友感覺BLL層意義不大,只是將DAL的數據提上來就轉發給了UI,而未作任何處理。看一下這個例子
BLL層
SelectUser(UserInfo userInfo)根據傳入的username或email得到用戶詳細信息。
IsExist(UserInfo userInfo)判斷指定的username或email是否存在。
然後DAL也相應提供方法共BLL調用
SelectUser(UserInfo userInfo)
IsExist(UserInfo userInfo)
這樣BLL確實只起到了一個傳遞的作用。
但如果這樣做:
BLL.IsExist(Userinfo userinfo)
{
UerInfo user = DAL.SelectUser(User);
return (userInfo.Id != null);
}
那麼DAL就無需實現IsExist()方法了,BLL中也就有了邏輯處理的代碼。
3、UserModel.cs
實體類,這個東西,大家可能覺得不好分層。包括我以前在內,是這樣理解的:UIßàModelßàBLLßàModelßàDAL,如此則認為Model在各層之間起到了一個數據傳輸的橋梁作用。不過在這裡,我們不是把事情想簡單,而是想復雜了。
Model是什麼?它什麼也不是!它在三層架構中是可有可無的。它其實就是面向對象編程中最基本的東西:類。一個桌子是一個類,一條新聞也是一個類,int、string、doublie等也是類,它僅僅是一個類而已。
這樣,Model在三層架構中的位置,和int,string等變量的地位就一樣了,沒有其它的目的,僅用於數據的存儲而已,只不過它存儲的是復雜的數據。所以如果你的項目中對象都非常簡單,那麼不用Model而直接傳遞多個參數也能做成三層架構。
那為什麼還要有Model呢,它的好處是什麼呢。下面是思考一個問題時想到的,插在這裡:
Model在各層參數傳遞時到底能起到做大的作用?
在各層間傳遞參數時,可以這樣:
AddUser(userId,userName,userPassword,…,)
也可以這樣:
AddUser(userInfo)
這兩種方法那個好呢。一目了然,肯定是第二種要好很多。
什麼時候用普通變量類型(int,string,guid,double)在各層之間傳遞參數,什麼使用Model傳遞?下面幾個方法:
SelectUser(int UserId)
SelectUserByName(string username)
SelectUserByName(string username,string password)
SelectUserByEmail(string email)
SelectUserByEmail(string email,string password)
可以概括為:
SelectUser(userId)
SelectUser(user)
這裡用user這個Model對象囊括了username,password,email這三個參數的四種組合模式。UserId其實也可以合並到user中,但項目中其它BLL都實現了帶有id參數的接口,所以這裡也保留這一項。
傳入了userInfo,那如何處理呢,這個就需要按照先後的順序了,有具體代碼決定。
這裡按這個順序處理
首先看是否同時具有username和password,然後看是否同時具有email和password,然後看是否有username,然後看是否有email。依次處理。
這樣,如果以後增加一個新內容,會員卡(number),則無需更改接口,只要在DAL的代碼中增加對number的支持就行,然後前台增加會員卡一項內容的表現與處理即可。
4、UserDAL.cs
public IList<UserInfo> SelectUsers():返回所有的用戶信息列表
public UserInfo SelectUser(int UserId):返回指定用戶的相信信息
public bool InsertUser(UserInfo User):新增用戶信息
public bool UpdateUser(UserInfo User):更新用戶信息
public void DeleteUser(int UserId):移除用戶信息
很多人最鬧不清的就是數據訪問層,到底那部分才算數據訪問層呢?有些認為數據庫就是數據訪問層,這是對定義沒有搞清楚,DAL是數據訪問層而不是數據存儲層,因此數據庫不可能是這一層的。也有的把SQLHelper(或其同類作用的組件)作為數據訪問層,它又是一個可有可無的東西,SQLHelper的作用是減少重復性編碼,提高編碼效率,因此如果我習慣在乎效率或使用一個非數據庫的數據源時,可以丟棄SQLHelper,一個可以隨意棄置的部分,又怎麼能成為三層架構中的一層呢。
可以這樣定義:與數據源操作有關的代碼,就應該放在數據訪問層中,屬於數據訪問層
5、IUserDAL
數據訪問層接口,這又是一個可有可無的東西,因為Petshop中帶了它和ClassFactory類工廠,所以有些項目不論需不需要支持多數據源,都把這兩個東西做了進來,有的甚至不建ClassFactory而只建了IDAL,然後“IUserDAL iUserDal = new UserDAL();”,不知意義何在。這就完全是畫虎不成反類犬了。
許多人在這裡有一個誤解,那就是以為存在這樣的關系:BLLßàIDALßàDAL,認為IDAL起到了BLL和DAL之間的橋梁作用,BLL是通過IDAL來調用DAL的。但實際是即使你如此編碼:“IUserDAL iUserDal = ClassFacotry.CreateUserDAL();”,那麼在執行“iUserDal.SelectUsers()”時,其實還是執行的UserDAL實例,而不是IUserDAL實例,所以IDAL在三層中的位置是與DAL平級的關系。
通過上面的介紹,基本上將三層架構的層次結構說明了。其實,本人有一個判斷三層架構是否標准的方法,那就是將三層中的任意一層完全替換,都不會對其它兩層造成影響,這樣的構造基本就符合三層標准了(雖然實現起來比較難^_^)。例如如果將項目從B/S改為C/S(或相反),那麼除了UI以外,BLL與DAL都不用改動;或者將SQLServer改為Oracle,只需替換SQLServerDAL到OracleDAL,無需其它操作等等。本來想在文中加入一些具體的代碼的,但感覺不是很必要,如果大家覺得需要的話,我再補充吧。
總結:不要因為某個層對你來說沒用,或者實現起來特別簡單,就認為它沒有必要,或者摒棄它,或者挪作它用。只要進行了分層,不管是幾層,每一層都要有明確的目的和功能實現,而不要被實際過程所左右,造成同一類文件位於不同層的情況發生。也不要出現同一層實現了不同的功能的情況發生。
前段時間寫了《實戰剖析三層架構》,看有些朋友希望提供一下代碼。但近期博客園上關於三層架構的文章很多,而且寫得都很好,所以就不准備被再寫了。不過這幾天又有朋友留言鼓勵,而且編程中發現一段比較合適的,所以還是決定寫出來共享給大家。
先簡要介紹一下,這個模塊是一個商品管理模塊。程序中實現了商品的浏覽、添加、修改等功能。
Model項目,商品品牌實體類,BrandInfo.cs:
using System;
namespace JKL.eShop.Model
{
/// <summary>
/// 品牌元數據
/// </summary>
[Serializable]
public class BrandInfo
{
/***************************************************
* 成員列表
***************************************************/
//品牌Id
private int _Id;
//品牌名稱
private string _Name;
//排序編號
private int _Number;
//是否為推薦品牌
private bool _IsVouch;
/***************************************************
* 屬性列表
***************************************************/
/// <summary>
/// 品牌Id
/// </summary>
public int Id
{
get { return _Id; }
set { _Id = value; }
}
/// <summary>
/// 品牌名稱
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
/// <summary>
/// 排序編號
/// </summary>
public int OrderNumber
{
get { return _Number; }
set { _Number = value; }
}
/// <summary>
/// 是否推薦品牌
/// </summary>
public bool IsVouch
{
get { return _IsVouch; }
set { _IsVouch = value; }
}
public string Vouch
{
get
{
if (_IsVouch)
{
return "推薦品牌";
}
else
{
return "普通品牌";
}
}
}
/***************************************************
* 構造函數
***************************************************/
public BrandInfo() { }
public BrandInfo(int id, string name)
{
_Id = id;
_Name = name;
}
public BrandInfo(int id, string name, int orderNumber, bool isVouch)
{
_Id = id;
_Name = name;
_Number = orderNumber;
_IsVouch = isVouch;
}
}
}
Model項目:GoodSortInfo.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace JKL.eShop.Model
{
/// <summary>
/// 分類實體類
/// </summary>
[Serializable]
public class GoodSortInfo
{
/***************************************************
* 成員列表
***************************************************/
//分類Id
private int _Id;
//分類名稱
private string _Name;
//級別
private int _Layer;
//上級分類
private GoodSortInfo _ParentSort;
//下級分類數量
private int _ChildNumber;
//備注
private string _Remark;
/***************************************************
* 屬性列表
***************************************************/
/// <summary>
/// 分類Id
/// </summary>
public int Id
{
get { return _Id; }
set { _Id = value; }
}
/// <summary>
/// 分類名稱
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
/// <summary>
/// 分類等級
/// </summary>
public int Layer
{
get { return _Layer; }
set { _Layer = value; }
}
/// <summary>
/// 上級分類
/// </summary>
public GoodSortInfo ParentSort
{
get { return _ParentSort; }
set { _ParentSort = value; }
}
/// <summary>
/// 上級分類Id
/// </summary>
public int ParentId
{
get { return _ParentSort.Id; }
}
/// <summary>
/// 下級分類數量
/// </summary>
public int ChildSortCount
{
get { return _ChildNumber; }
set { _ChildNumber = value; }
}
/// <summary>
/// 備注
/// </summary>
public string Remark
{
get { return _Remark; }
set { _Remark = value; }
}
/***************************************************
* 構造函數
***************************************************/
public GoodSortInfo() { }
public GoodSortInfo(int id)
{
_Id = id;
}
public GoodSortInfo(int id, string name)
{
_Id = id;
_Name = name;
}
public GoodSortInfo(int id, string name, int depth, int childNumber)
{
_Id = id;
_Name = name;
_Layer = depth;
_ChildNumber = childNumber;
}
}
}
Model項目,GoodInfo.cs:
using System;
using System.Collections;
using System.Collections.Generic;
namespace JKL.eShop.Model
{
/// <summary>
/// 商品元數據
/// </summary>
[Serializable]
public class GoodInfo
{
/***************************************************
* 成員列表
***************************************************/
//商品Id
private int _Id;
//商品名稱
private string _Name;
//品牌
private BrandInfo _BrandInfo;
//分類
private GoodSortInfo _SortInfo;
//商品編碼
private string _Code;
//條形碼
private string _Barcode;
//單位(個/盒/袋等)
private string _Unit;
//規格
private string _Standard;
//簡介
private string _SimpleIntroduction;
//詳細說明
private string _DetailIntroduction;
//圖片路徑
private string _PicturePath;
//發布日期
private DateTime _PublicTime;
//更新日期
private DateTime _UpdateTime;
//市場價
private decimal _MarketPrice;
//零售價
private decimal _SellPrice;
//贈送積分
private decimal _Score;
//浏覽次數
private int _ClickCount;
//上一次浏覽時間
private DateTime _ClickTime;
//商品種類
private string _KindName;
//庫存數量
private int _Stock;
//是否顯示
private bool _Visable = false;
#region 關鍵字段枚舉
private static Hashtable _KindList;
private static Hashtable _PopList;
#endregion
/***************************************************
* 屬性列表
***************************************************/
public int Id
{
get { return _Id; }
set { _Id = value; }
}
/// <summary>
/// 商品編碼
/// </summary>
public string Code
{
get { return _Code; }
set { _Code = value; }
}
/// <summary>
/// 條形碼
/// </summary>
public string Barcode
{
get { return _Barcode; }
set { _Barcode = value; }
}
/// <summary>
/// 品牌
/// </summary>
public BrandInfo BrandInfo
{
get
{
if (_BrandInfo == null)
{
_BrandInfo = new BrandInfo();
}
return _BrandInfo;
}
set { _BrandInfo = value; }
}
/// <summary>
/// 品牌名稱
/// </summary>
public string BrandName
{
get { return this.BrandInfo.Name; }
set { this.BrandInfo.Name = value; }
}
/// <summary>
/// 商品分類
/// </summary>
public GoodSortInfo Sort
{
get { return _SortInfo; }
set { _SortInfo = value; }
}
/// <summary>
/// 商品名稱
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
/// <summary>
/// 單位(個/盒/袋等)
/// </summary>
public string Unit
{
get { return _Unit; }
set { _Unit = value; }
}
/// <summary>
/// 規格
/// </summary>
public string Standard
{
get { return _Standard; }
set { _Standard = value; }
}
/// <summary>
/// 簡介
/// </summary>
public string SimpleIntroduction
{
get { return _SimpleIntroduction; }
set { _SimpleIntroduction = value; }
}
/// <summary>
/// 詳細說明
/// </summary>
public string DetailIntroduction
{
get { return _DetailIntroduction; }
set { _DetailIntroduction = value; }
}
/// <summary>
/// 圖片路徑
/// </summary>
public string PicturePath
{
get { return _PicturePath; }
set { _PicturePath = value; }
}
/// <summary>
/// 發布日期
/// </summary>
public DateTime PublicTime
{
get { return _PublicTime; }
set { _PublicTime = value; }
}
/// <summary>
/// 更新日期
/// </summary>
public DateTime UpdateTime
{
get { return _UpdateTime; }
set { _UpdateTime = value; }
}
/// <summary>
/// 市場價
/// </summary>
public decimal MarketPrice
{
get { return _MarketPrice; }
set { _MarketPrice = value; }
}
/// <summary>
/// 零售價
/// </summary>
public decimal SellPrice
{
get { return _SellPrice; }
set { _SellPrice = value; }
}
/// <summary>
/// 贈送積分
/// </summary>
public decimal Score
{
get { return _Score; }
set { _Score = value; }
}
/// <summary>
/// 浏覽次數
/// </summary>
public int ClickCount
{
get { return _ClickCount; }
set { _ClickCount = value; }
}
/// <summary>
/// 上次浏覽時間
/// </summary>
public DateTime ClickTime
{
get { return _ClickTime; }
set { _ClickTime = value; }
}
public string KindName
{
get { return _KindName; }
set { _KindName = value; }
}
/// <summary>
/// 庫存數量
/// </summary>
public int Stock
{
get { return _Stock; }
set { _Stock = value; }
}
/// <summary>
/// 是否顯示
/// </summary>
public bool Visable
{
get { return _Visable; }
set { _Visable = value; }
}
/***************************************************
* 構造函數
***************************************************/
public GoodInfo() { }
public GoodInfo(int id, string code, string name, string picturePath, decimal marketPrice, decimal sellPrice, string unit, string standard, int stock)
{
_Id = id;
_Code = code;
_Name = name;
_PicturePath = picturePath;
_MarketPrice = marketPrice;
_SellPrice = sellPrice;
_Unit = unit;
_Standard = standard;
_Stock = stock;
}
public GoodInfo(int id, string code, string name, string picturePath, string brandName, string kindName, string standard, string simpleIntroduction, DateTime publicTime, decimal marketPrice, decimal sellPrice, string unit, decimal score, int clickNumber)
{
_Id = id;
_Code = code;
_Name = name;
_PicturePath = picturePath;
this.BrandName = brandName;
_KindName = kindName;
_Standard = standard;
_SimpleIntroduction = simpleIntroduction;
_PublicTime = publicTime;
_MarketPrice = marketPrice ;
_SellPrice = sellPrice;
_Unit = unit;
_Score = score;
_ClickCount = clickNumber;
_Stock = Stock;
}
public GoodInfo(int id, string code, string name, string picturePath, string brandName, string kindName, string standard, string simpleIntroduction, string detailIntroduction, decimal marketPrice, decimal sellPrice, string unit, decimal score, int clickNumber, DateTime publicTime, int stock)
{
_Id = id;
_Code = code;
_Name = name;
_PicturePath = picturePath;
this.BrandName = brandName;
_KindName = kindName;
_Standard = standard;
_SimpleIntroduction = simpleIntroduction;
_DetailIntroduction = detailIntroduction;
_MarketPrice = marketPrice;
_SellPrice = sellPrice;
_Unit = unit;
_Score = score;
_ClickCount = clickNumber;
_PublicTime = publicTime;
_Stock = stock;
}
}
}
BLL項目:GoodBLL.cs
using System;
using System.Collections.Generic;
using JKL.eShop.DAL;
using JKL.eShop.Model;
namespace JKL.eShop.BLL
{
/// <summary>
///
/// </summary>
public class GoodBLL
{
/* **************************************************
* 成員列表
* *************************************************/
private GoodDAL _GoodDal = null;
/* **************************************************
* 屬性列表
* *************************************************/
private GoodDAL GoodDal
{
get
{
if (_GoodDal == null)
{
_GoodDal = new GoodDAL();
}
return _GoodDal;
}
}
/* **************************************************
* 公共方法
* *************************************************/
/// <summary>
/// 更新商品信息
/// </summary>
/// <param name="goodInfo"></param>
/// <returns></returns>
public bool ChangeGood(GoodInfo goodInfo)
{
return false;
}
/// <summary>
/// 商品變價
/// </summary>
/// <param name="goodinfo"></param>
/// <returns></returns>
public bool ChangePrice(GoodInfo goodinfo)
{
return this.GoodDal.UpdateGoodsPrice(goodinfo);
}
/// <summary>
/// 根據ID返回商品的詳細信息
/// </summary>
/// <param name="goodId"></param>
/// <returns></returns>
public GoodInfo GetGood(int goodId)
{
GoodInfo good = this.GoodDal.SelectGood(goodId);
good.ClickCount++;
this.GoodDal.UpdateGood(good);
return good;
}
#region 返回商品信息列表
/// <summary>
/// 返回所有商品的列表
/// </summary>
/// <returns></returns>
public IList<GoodInfo> GetGoodsList()
{
return this.GoodDal.SelectGoods();
}
/// <summary>
/// 返回指定分類的所屬商品列表
/// </summary>
/// <param name="sortId">分類Id</param>
/// <returns></returns>
public IList<GoodInfo> GetGoodsListBySort(int sortId)
{
return this.GoodDal.SelectGoodsBySort(sortId);
}
/// <summary>
/// 根據熱門程度的類型返回商品列表
/// </summary>
/// <param name="sortId"></param>
/// <returns></returns>
public IList<GoodInfo> GetGoodsListByPop(string popKind)
{
return this.GoodDal.SelectGoodsListByPop(1000, popKind);
}
/// <summary>
/// 返回指定品牌的所屬商品列表
/// </summary>
/// <param name="brandName"></param>
/// <returns></returns>
public IList<GoodInfo> GetGoodsListByBrand(string brandName)
{
GoodDAL goodDal = new GoodDAL();
return goodDal.SelectGoodsListByBrand(brandName);
}
public IList<GoodInfo> GetGoodsBrief()
{
return this.GoodDal.SelectGoodsBrief();
}
/// <summary>
///
/// </summary>
/// <param name="topNumber"></param>
/// <param name="kindName"></param>
/// <returns></returns>
public IList<GoodInfo> GetGoodsBriefByKind(int topNumber, string kindName)
{
return this.GoodDal.SelectGoodsBriefByKind(topNumber, kindName);
}
public IList<GoodInfo> GetGoodsListByKind(string kindName)
{
return this.GoodDal.SelectGoodsListByKind(kindName);
}
#endregion
#region 商品查詢部分
public IList<GoodInfo> QueryGoodsList(string keyword)
{
GoodDAL goodDal = new GoodDAL();
return goodDal.SelectGoodsListByKeyword(keyword);
}
#endregion
}
}
DAL項目:GoodDAL.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using KoalaStudio.Data.SqlServer;
using JKL.eShop.Model;
namespace JKL.eShop.DAL
{
/// <summary>
///
/// </summary>
public class GoodDAL
{
/* **************************************************
* 成員列表
* **************************************************/
/* **************************************************
* 屬性列表
* **************************************************/
/* **************************************************
* 構造函數
* **************************************************/
public GoodDAL() { }
/* **************************************************
* 私有和受保護方法
* **************************************************/
/// <summary>
///
/// </summary>
/// <param name="sqlText"></param>
/// <returns></returns>
private IList<GoodInfo> SelectGoodsBrief(string sqlText)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = sqlText;
SqlDataReader dr = cmd.ExecuteReader();
IList<GoodInfo> goods = new List<GoodInfo>();
SortDAL sortDal = new SortDAL();
if (dr.HasRows)
{
while (dr.Read())
{
GoodInfo good = new GoodInfo();
good.Id = Convert.ToInt32(dr["Id"]); ;
good.Code = dr["dianneima"].ToString();
good.Name = dr["Name"].ToString();
string picturePath = dr["Picture"].ToString();
good.PicturePath = picturePath.Substring(0, picturePath.IndexOf("|||"));
good.MarketPrice = Convert.ToDecimal(dr["MarketPrice"]); ;
good.SellPrice = Convert.ToDecimal(dr["MemberPrice"]);
good.Unit = dr["DanWei"].ToString();
good.Standard = dr["GuiGe"].ToString();
goods.Add(good);
}
dr.Close();
cmd.Disconnection();
}
return goods;
}
/// <summary>
///
/// </summary>
/// <param name="sqlText"></param>
/// <returns></returns>
private IList<GoodInfo> SelectGoodsList(string sqlText)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = sqlText;
SqlDataReader dr = cmd.ExecuteReader();
IList<GoodInfo> goods = new List<GoodInfo>();
SortDAL sortDal = new SortDAL();
if (dr.HasRows)
{
while (dr.Read())
{
GoodInfo good = new GoodInfo();
good.Id = Convert.ToInt32(dr["Id"]);
good.Name = dr["Name"].ToString();
good.BrandInfo.Name = dr["Brand"].ToString();
good.Code = dr["dianneima"].ToString();
string picturePath = dr["Picture"].ToString();
good.PicturePath = picturePath.Substring(0, picturePath.IndexOf("|||"));
good.KindName = dr["Kind"].ToString();
good.Standard = dr["GuiGe"].ToString();
good.SimpleIntroduction = dr["Introduce"].ToString();
good.PublicTime = Convert.ToDateTime(dr["JoinDate"]);
good.MarketPrice = Convert.ToDecimal(dr["MarketPrice"]); ;
good.SellPrice = Convert.ToDecimal(dr["MemberPrice"]);
good.Unit = dr["DanWei"].ToString();
good.Score = Convert.ToDecimal(dr["Score"]);
good.ClickCount = Convert.ToInt32(dr["TotalHits"]);
goods.Add(good);
}
dr.Close();
cmd.Disconnection();
}
return goods;
}
/* **************************************************
* 公共方法
* **************************************************/
/// <summary>
/// 更新商品的價格和庫存信息
/// </summary>
/// <returns></returns>
public bool UpdateGoodsPrice(GoodInfo goodInfo)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = "UPDATE SW_Product SET MarketPrice = " + goodInfo.MarketPrice + ", MemberPrice = " + goodInfo.SellPrice + ", Stock = " + goodInfo.Stock + ", ModiDate = '" + DateTime.Now + "' WHERE Id = " + goodInfo.Id;
cmd.ExecuteNonQuery();
return true;
}
/// <summary>
/// 更新商品信息
/// 當前僅支持更新點擊率一項
/// </summary>
/// <param name="good"></param>
/// <returns></returns>
public bool UpdateGood(GoodInfo good)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = "UPDATE eShop_Goods SET ClickCount = " + good.ClickCount + " WHERE GoodId = " + good.Id;
cmd.ExecuteNonQuery();
return true;
}
/// <summary>
/// 返回所有商品列表
/// </summary>
/// <returns></returns>
public IList<GoodInfo> SelectGoods()
{
string sqlText = "SELECT * FROM eShop_Goods";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 返回指定分類的所屬商品列表
/// </summary>
/// <param name="sortId"></param>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsBySort(int sortId)
{
string sqlText = "SELECT * FROM SW_Product WHERE Hide = 0 AND ClassId IN (SELECT ClassId FROM SW_Class WHERE Parentstr LIKE '%" + sortId + "%' OR ClassId = " + sortId + ")";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 返回指定排行類型的所屬商品列表
/// </summary>
/// <param name="topNumber"></param>
/// <param name="popName"></param>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsByPop(int topNumber, string popName)
{
string sqlText = "SELECT TOP " + topNumber + " Id, dianneima, Name, Picture, Brand, GuiGe, CASE Kind WHEN 0 THEN '最新上架' WHEN 1 THEN '推薦商品' WHEN 2 THEN '特價商品' END AS Kind, Introduce, JoinDate, MarketPrice, MemberPrice, DanWei, Score, TotalHits, Stock FROM SW_Product WHERE Hide = 0 ORDER BY " + GoodInfo.PopList[popName].ToString() + " DESC";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 返回指定品牌的所屬商品列表
/// </summary>
/// <param name="brandName"></param>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsByBrand(string brandName)
{
string sqlText = "SELECT * FROM SW_Product WHERE Hide = 0 AND Brand = '" + brandName + "'";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 返回所有商品列表,按簡要說明返回
/// </summary>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsBrief()
{
string sqlText = "SELECT Id, dianneima, Name, Picture, MarketPrice, MemberPrice, DanWei, GuiGe, Stock FROM SW_Product";
return this.SelectGoodsBrief(sqlText);
}
/// <summary>
/// 返回指定分區的所屬商品列表,按簡要說明返回
/// </summary>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsBriefByKind(int topNumber, string kindName)
{
string sqlText = "SELECT TOP " + topNumber + " Id, dianneima, Name, Picture, MarketPrice, MemberPrice, DanWei, GuiGe, Stock FROM SW_Product WHERE Hide = 0 AND Kind = " + GoodInfo.KindList[kindName].ToString() + " ORDER BY JoinDate DESC";
return this.SelectGoodsBrief(sqlText);
}
/// <summary>
/// 返回指定分區的所屬商品列表
/// </summary>
/// <param name="kindName"></param>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsListByKind(string kindName)
{
string sqlText = "SELECT Id, dianneima, Name, Picture, Brand, GuiGe, CASE Kind WHEN 0 THEN '最新上架' WHEN 1 THEN '推薦商品' WHEN 2 THEN '特價商品' END AS Kind, Introduce, JoinDate, MarketPrice, MemberPrice, DanWei, Score, TotalHits, Stock FROM SW_Product WHERE Hide = 0 AND (Kind = " + GoodInfo.KindList[kindName].ToString() + ") ORDER BY JoinDate DESC";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 返回商品的詳細信息
/// </summary>
/// <param name="goodId"></param>
/// <returns></returns>
public GoodInfo SelectGood(int goodId)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = "SELECT TOP 1 Id, dianneima, Name, Picture, Brand, GuiGe, CASE Kind WHEN 0 THEN '最新上架' WHEN 1 THEN '推薦商品' WHEN 2 THEN '特價商品' END AS Kind, Introduce, JoinDate, Detail, MarketPrice, MemberPrice, DanWei, Score, TotalHits, Stock FROM SW_Product WHERE Hide = 0 AND Id = " + goodId;
SqlDataReader dr = cmd.ExecuteReader();
GoodInfo good;
if (dr.HasRows)
{
dr.Read();
string picturePath = dr["Picture"].ToString();
picturePath = picturePath.Substring(0, picturePath.IndexOf("|||"));
good = new GoodInfo(Convert.ToInt32(dr["Id"]), dr["dianneima"].ToString(), dr["Name"].ToString(), picturePath, dr["Brand"].ToString(), dr["Kind"].ToString(), dr["GuiGe"].ToString(), dr["Introduce"].ToString(), dr["Detail"].ToString(), Convert.ToDecimal(dr["MarketPrice"]), Convert.ToDecimal(dr["MemberPrice"]), dr["DanWei"].ToString(), Convert.ToDecimal(dr["Score"]), Convert.ToInt32(dr["TotalHits"]), Convert.ToDateTime(dr["JoinDate"]), Convert.ToInt32(dr["Stock"]));
dr.Close();
cmd.Disconnection();
}
else
{
good = new GoodInfo();
}
return good;
}
/// <summary>
/// 根據關鍵字返回商品列表
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
public IList<GoodInfo> SelectGoodsListByKeyword(string keyword)
{
string sqlText = "SELECT Id, dianneima, Name, Picture, Brand, GuiGe, CASE Kind WHEN 0 THEN '最新上架' WHEN 1 THEN '推薦商品' WHEN 2 THEN '特價商品' END AS Kind, Introduce, JoinDate, MarketPrice, MemberPrice, DanWei, Score, TotalHits, Stock FROM SW_Product WHERE Hide = 0 AND Name like '%" + keyword + "%'";
return this.SelectGoodsList(sqlText);
}
/// <summary>
/// 新增商品
/// </summary>
/// <param name="good"></param>
/// <returns></returns>
public bool InsertGood(GoodInfo good)
{
CmdCommand cmd = new CmdCommand();
cmd.CommandText = "INSERT INTO eShop_Goods (SortId, [Name], BrandId, Code, Barcode, Unit, [Standard], PicturePath, SimpleIntroduction, DetailIntroduction, MarketPrice, SellPrice, PublicTime, UpdateTime, ClickCount, ClickTime, Stock) VALUES (" + good.Sort.Id + ", '" + good.Name + "', " + good.BrandInfo.Id + ", '" + good.Code + "', '" + good.Barcode + "', '" + good.Unit + "', '" + good.Standard + "', '" + good.PicturePath + "', '" + good.SimpleIntroduction + "', '" + good.DetailIntroduction + "', " + good.MarketPrice + ", " + good.SellPrice + ", '" + good.PublicTime + "', '" + good.UpdateTime + "', " + good.ClickCount + ", '" + good.ClickTime + "', " + good.Stock + ")";
cmd.ExecuteNonQuery();
return true;
}
}
}