|
|
對(duì)軟件進(jìn)行分層可以達(dá)到結(jié)構(gòu)清晰、易于重用的目的。軟件的分層類似于社會(huì)的分工,有了分工,人們就可以專司其職,搞IT的就不用邊寫.NET程序邊種莊稼了。
在軟件結(jié)構(gòu)中,分層結(jié)構(gòu)是一種最易于理解的結(jié)構(gòu)。下面介紹的是一個(gè)簡(jiǎn)單的分層結(jié)構(gòu),它可以用在一些簡(jiǎn)單的項(xiàng)目上(實(shí)際上它正在被使用),如進(jìn)銷存系統(tǒng)這類主要和數(shù)據(jù)庫(kù)打交道的系統(tǒng)。
1、數(shù)據(jù)訪問層
(1)使用工廠模式實(shí)現(xiàn)的通用數(shù)據(jù)訪問功能。關(guān)于如何用工廠模式實(shí)現(xiàn)此功能,網(wǎng)上很多,實(shí)現(xiàn)起來也比較容易,可以使用IdbConnection、IdbCommand、IdbTransaction等接口。這里就不再說了。
(2)基于反射,實(shí)現(xiàn)“實(shí)體類<——>Sql語句”。包含BuildCreateObjSql(生成Insert語句)、BuildUpdateObjSql(生成Update語句)、BuildSelectObjSql(生成Select語句)、BuildObj(由IdataReade創(chuàng)建實(shí)體類對(duì)象,并為成員變量賦值)、BuildObjs(由DataTable生成實(shí)體類對(duì)象數(shù)組)等方法,方法實(shí)現(xiàn)過程類似如下(省略部分代碼,要求實(shí)體類名=數(shù)據(jù)庫(kù)表名,實(shí)體屬性名=數(shù)據(jù)庫(kù)表字段名):
public static string BuildCreateObjSql(object pObj)
{
…………
Type t= pObj.GetType();
PropertyInfo[] pis=t.GetProperties();
for(int i=0;i<PIS.LENGTH;I++)
{
switch(pis.PropertyType.ToString())
{
case"System.Int32":
fieldString+=pis.Name;
valueString+=pis.GetValue(pObj,null).ToString();
break;
case"System.String":
…………
}
if(i<PIS.LENGTH-1)
{
fieldString+=",";
valueString+=",";
}
}
result="insert into "+t.Name+"("+fieldString+") values("+valueString+")"+";";
return result;
}
public static object BuildObj(string pClassName,IDataReader pReader)
{
Type t=Type.GetType(namespace+ pClassName);
PropertyInfo[] pis=t.GetProperties();
object obj=Activator.CreateInstance(t);
BindValue (obj,pis,pReader); //為各字段賦值
return obj;
}
private static void BindValue (object pObj,PropertyInfo[] pPis,IDataReader pReader)
{
for(int i=0;i<PPIS.LENGTH;I++)
{
for(int j=0;j<PREADER.FIELDCOUNT;J++)
{
switch(pPis.PropertyType.ToString())
{
case"System.Int32":
pPis.SetValue(pObj,int.Parse(pReader[pPis.Name].ToString()),null);
break;
case"System.String":
…………;
break;
}
}
}
}
2、實(shí)體層
該層包含所有的實(shí)體類。假設(shè)數(shù)據(jù)庫(kù)中存在一表叫Book的表,包括id,bookname,price,authorid字段,那么對(duì)應(yīng)的實(shí)體類類似如下(當(dāng)數(shù)據(jù)庫(kù)表數(shù)量較多時(shí),編寫實(shí)體類的工作會(huì)顯示枯燥無味,好像現(xiàn)在有不少工具可以完成由數(shù)據(jù)庫(kù)表生成實(shí)體類文件的工作):
public class Book : EntityHome
{
private string m_BookName;
private decimal m_Price;
private int m_AuthorID;
public Book()
{
}
public Book(int ID,string BookName, decimal Price, int AuthorID)
{
this.ID=ID;
this.BookName=BookName;
this.Price=Price;
this.AuthorID=AuthorID;
}
public string BookName
{
get
{
return this.m_BookName;
}
set
{
this.m_BookName=value;
}
}
public decimal Price
{
…………
}
public int AuthorID
{
…………
}
}
3、業(yè)務(wù)層:
在業(yè)務(wù)層中,包含了所有的控制類,它們與上面的實(shí)體類一一對(duì)應(yīng),主要的繼承鏈?zhǔn)加冢篠ingleHomeCtr(處理單個(gè)實(shí)體類的控制類基類);MultiHomeCtr(處理多個(gè)實(shí)體類的控制類),類似如下:
public class BookCtr:SingleHomeCtr
{
public BookCtr()
{
}
public void CreateObj(Book obj)
{
//通過數(shù)據(jù)訪問層中的反射方法,生成sql語句,并最終持久化成數(shù)據(jù)庫(kù)表中的一條記錄。
…………
}
public Book RetrieveObj(int id)
{
//通過數(shù)據(jù)訪問層中的方法,生成sql語句,并最終返回一個(gè)Book對(duì)象。
…………
}
public void UpdateObj(Book obj)
{
//通過數(shù)據(jù)訪問層中的反射方法,生成sql語句,并最終持久化成數(shù)據(jù)庫(kù)表中的一條記錄。
…………
}
}
4、UI層
有了以上的準(zhǔn)備工作,在界面上對(duì)數(shù)據(jù)庫(kù)的操作,就可以“對(duì)象化”了,例如根據(jù)數(shù)據(jù)庫(kù)表的一條記錄創(chuàng)建一個(gè)Book對(duì)象:
Book b = null;
BookCtr bctr = new BookCtr();
b = bctr.RetrieveObj(id);
或者持久化一條數(shù)據(jù)到數(shù)據(jù)庫(kù)(對(duì)象的CreateObj方法)、或者更新一條數(shù)據(jù)庫(kù)記錄(對(duì)象的UpdateObj方法)。
5、最后
在這個(gè)結(jié)構(gòu)中包含了OR映射的概念。OR映射主要解決對(duì)象與關(guān)系數(shù)據(jù)之間的映射以及對(duì)象的持久化問題,翻譯成白話就是怎么樣把對(duì)數(shù)據(jù)庫(kù)的操作歸結(jié)到對(duì)對(duì)象的操作。這個(gè)工作有許多復(fù)雜的地方,不是憑借一己之力以完成的。所以在上面的示例中,實(shí)際情況是只能完成一些簡(jiǎn)單的映射,對(duì)于一些所謂的“粗粒度對(duì)象”(即一個(gè)對(duì)象需要關(guān)聯(lián)多個(gè)數(shù)據(jù)庫(kù)表)的映射,實(shí)現(xiàn)起來比較困難。來原: www |
|