模式与架构系列之二:分层、反射与OR映射

对软件进行分层可以达到结构清晰、易于重用的目的。软件的分层类似于社会的分工,有了分工,人们就可以专司其职,搞IT的就不用边写.NET程序边种庄稼了。

在软件结构中,分层结构是一种最易于理解的结构。下面介绍的是一个简单的分层结构,它可以用在一些简单的项目上(实际上它正在被使用),如进销存系统这类主要和数据库打交道的系统。

1、数据访问层
(1)使用工厂模式实现的通用数据访问功能。关于如何用工厂模式实现此功能,网上很多,实现起来也比较容易,可以使用IdbConnectionIdbCommandIdbTransaction等接口。这里就不再说了。

(2)基于反射,实现“实体类<——>Sql语句”。包含BuildCreateObjSql(生成Insert语句)、BuildUpdateObjSql(生成Update语句)、BuildSelectObjSql(生成Select语句)、BuildObj(由IdataReade创建实体类对象,并为成员变量赋值)、BuildObjs(由DataTable生成实体类对象数组)等方法,方法实现过程类似如下(省略部分代码,要求实体类名=数据库表名,实体属性名=数据库表字段名):

public static string BuildCreateObjSql(object pObj)
{
    …………
    Type t
= pObj.GetType();
    PropertyInfo[] pis
=t.GetProperties();
    
for(int i=0;i<pis.Length;i++)
    
{
        
switch(pis[i].PropertyType.ToString())
        
{
            
case"System.Int32":
                fieldString
+=pis[i].Name;
                valueString
+=pis[i].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[i].PropertyType.ToString())
            
{
                
case"System.Int32":
                    pPis[i].SetValue(pObj,
int.Parse(pReader[pPis[i].Name].ToString()),null);
                    
break;
                
case"System.String":
                    …………;
                    
break;
            }

        }

    }

}

2

、实体层
该层包含所有的实体类。假设数据库中存在一表叫Book的表,包括id,bookname,price,authorid字段,那么对应的实体类类似如下(当数据库表数量较多时,编写实体类的工作会显示枯燥无味,好像现在有不少工具可以完成由数据库表生成实体类文件的工作):

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、业务层:
在业务层中,包含了所有的控制类,它们与上面的实体类一一对应,主要的继承链始于:SingleHomeCtr(处理单个实体类的控制类基类);MultiHomeCtr(处理多个实体类的控制类),类似如下:

public class BookCtr:SingleHomeCtr
{
    
public BookCtr()
    
{
    }


    
public void CreateObj(Book obj)
    
{
        
//通过数据访问层中的反射方法,生成sql语句,并最终持久化成数据库表中的一条记录。
        …………
    }


    
public Book RetrieveObj(int id)
    
{
        
//通过数据访问层中的方法,生成sql语句,并最终返回一个Book对象。
        …………
    }


    
public void UpdateObj(Book obj)
    
{
        
//通过数据访问层中的反射方法,生成sql语句,并最终持久化成数据库表中的一条记录。
        …………
    }

}

4UI
有了以上的准备工作,在界面上对数据库的操作,就可以“对象化”了,例如根据数据库表的一条记录创建一个Book对象:
Book b = null;
BookCtr bctr = new BookCtr();
b = bctr.RetrieveObj(id);
或者持久化一条数据到数据库(对象的CreateObj方法)、或者更新一条数据库记录(对象的UpdateObj方法)

5、最后
在这个结构中包含了OR映射的概念。OR映射主要解决对象与关系数据之间的映射以及对象的持久化问题,翻译成白话就是怎么样把对数据库的操作归结到对对象的操作。这个工作有许多复杂的地方,不是凭借一己之力以完成的。所以在上面的示例中,实际情况是只能完成一些简单的映射,对于一些所谓的“粗粒度对象”(即一个对象需要关联多个数据库表)的映射,实现起来比较困难。

原文地址:https://www.cnblogs.com/morvenhuang/p/971775.html