对软件进行分层可以达到结构清晰、易于重用的目的。软件的分层类似于社会的分工,有了分工,人们就可以专司其职,搞IT的就不用边写.NET程序边种庄稼了。
在软件结构中,分层结构是一种最易于理解的结构。下面介绍的是一个简单的分层结构,它可以用在一些简单的项目上(实际上它正在被使用),如进销存系统这类主要和数据库打交道的系统。
1、数据访问层
(1)使用工厂模式实现的通用数据访问功能。关于如何用工厂模式实现此功能,网上很多,实现起来也比较容易,可以使用IdbConnection、IdbCommand、IdbTransaction等接口。这里就不再说了。
(2)基于反射,实现“实体类<——>Sql语句”。包含BuildCreateObjSql(生成Insert语句)、BuildUpdateObjSql(生成Update语句)、BuildSelectObjSql(生成Select语句)、BuildObj(由IdataReade创建实体类对象,并为成员变量赋值)、BuildObjs(由DataTable生成实体类对象数组)等方法,方法实现过程类似如下(省略部分代码,要求实体类名=数据库表名,实体属性名=数据库表字段名):
public static string BuildCreateObjSql(object pObj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
…………
Type t= pObj.GetType();
PropertyInfo[] pis=t.GetProperties();
for(int i=0;i<pis.Length;i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
switch(pis[i].PropertyType.ToString())
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case"System.Int32":
fieldString+=pis[i].Name;
valueString+=pis[i].GetValue(pObj,null).ToString();
break;
case"System.String":
…………
}
if(i<pis.Length-1)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
fieldString+=",";
valueString+=",";
}
}
result="insert into "+t.Name+"("+fieldString+") values("+valueString+")"+";";
return result;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
public static object BuildObj(string pClassName,IDataReader pReader)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
Type t=Type.GetType(namespace+ pClassName);
PropertyInfo[] pis=t.GetProperties();
object obj=Activator.CreateInstance(t);
BindValue (obj,pis,pReader); //为各字段赋值
return obj;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private static void BindValue (object pObj,PropertyInfo[] pPis,IDataReader pReader)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
for(int i=0;i<pPis.Length;i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(int j=0;j<pReader.FieldCount;j++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
switch(pPis[i].PropertyType.ToString())
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case"System.Int32":
pPis[i].SetValue(pObj,int.Parse(pReader[pPis[i].Name].ToString()),null);
break;
case"System.String":
…………;
break;
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
、实体层
该层包含所有的实体类。假设数据库中存在一表叫Book的表,包括id,bookname,price,authorid字段,那么对应的实体类类似如下(当数据库表数量较多时,编写实体类的工作会显示枯燥无味,好像现在有不少工具可以完成由数据库表生成实体类文件的工作):
public class Book : EntityHome
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
private string m_BookName;
private decimal m_Price;
private int m_AuthorID;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Book()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
public Book(int ID,string BookName, decimal Price, int AuthorID)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.ID=ID;
this.BookName=BookName;
this.Price=Price;
this.AuthorID=AuthorID;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public string BookName
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this.m_BookName;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.m_BookName=value;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public decimal Price
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
…………
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public int AuthorID
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
…………
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3、业务层:
在业务层中,包含了所有的控制类,它们与上面的实体类一一对应,主要的继承链始于:SingleHomeCtr(处理单个实体类的控制类基类);MultiHomeCtr(处理多个实体类的控制类),类似如下:
public class BookCtr:SingleHomeCtr
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public BookCtr()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void CreateObj(Book obj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//通过数据访问层中的反射方法,生成sql语句,并最终持久化成数据库表中的一条记录。
…………
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Book RetrieveObj(int id)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//通过数据访问层中的方法,生成sql语句,并最终返回一个Book对象。
…………
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void UpdateObj(Book obj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//通过数据访问层中的反射方法,生成sql语句,并最终持久化成数据库表中的一条记录。
…………
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4、UI层
有了以上的准备工作,在界面上对数据库的操作,就可以“对象化”了,例如根据数据库表的一条记录创建一个Book对象:
Book b = null;
BookCtr bctr = new BookCtr();
b = bctr.RetrieveObj(id);
或者持久化一条数据到数据库(对象的CreateObj方法)、或者更新一条数据库记录(对象的UpdateObj方法)。
5、最后
在这个结构中包含了OR映射的概念。OR映射主要解决对象与关系数据之间的映射以及对象的持久化问题,翻译成白话就是怎么样把对数据库的操作归结到对对象的操作。这个工作有许多复杂的地方,不是凭借一己之力以完成的。所以在上面的示例中,实际情况是只能完成一些简单的映射,对于一些所谓的“粗粒度对象”(即一个对象需要关联多个数据库表)的映射,实现起来比较困难。