一步步构建多层架构系列我将以我原来开发过的海关项目系统为例,但仅抽像出系统架构部分,大致图形如下:

 

说明:我会一步步完善上面的框架,其中会用到设计模式,webservice构建同步,缓存等

开发.net项目时,我们一般采用三层结构,微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层、表示层。

数据访问层(dal):主要用来访问数据库的增删改查的操作,只不过将对数据库的增删改查封装了而已。这里我们使用微软已封装好的sqlhelp类作为底层数据库操作类,也就是指运用了sqlconnection,sqlcommand,sqlapdater等几个类的操作。

业务逻辑层(bll):主要用于调用数据访问层dal,其中需要传递对象到数据访问层,这个层主要封装了一些业务逻辑,方便界面层来调用。

表示层:是系统的UI部分,负责使用者与整个系统的交互。在这一层中,理想的状态是不应包括系统的业务逻辑。表示层中的逻辑代码,仅与界面元素有关。

具体搭建方法如下:

1.根据客户需求,客户需要同时支持mysql和sqlserver,所以首先我们需要添加底库sqlhelper和mysqlhelper,建立如下图所示的类库,并添加sqlhelper.cs和mysqlhelper.cs,如下图所示:,其中sqlhelper.cs和mysqlhelper类在此处下载/Files/mfm11111/Pyllot.EC.DBUlitily.rar

2.建立DAL数据访问层,因为要同时支持mysql和sqlserver,所以我们需要建立Pyllot.EC.MySqlDal与Pyllot.EC.SqlServerDal类库。以默认数据库pubs库中的Category为例,于是我们构建如下所示的代码,也就是一般的增删改查:

 

Code
using System;
using System.Collections.Generic;
using System.Text;
using Pyllot.EC.Cargo.IDAL;
using System.Data;
using Pyllot.EC.DBUtility;
using Pyllot.EC.Common;
using Pyllot.EC.Cargo.Model;
using MySql.Data.MySqlClient;

namespace Pyllot.EC.Cargo.MySqlDAL
{
    
public class Category:ICategory
    
{
        
public DataSet GetAll()
        
{
            
return Pyllot.EC.DBUtility.MySqlHelper.ExecuteDataset(ConnectionProvider.connStringMySql, CommandType.Text, "select * from op_job");
        }


        
// 选择按照条件
        public DataTable SelectByCondition(string strCondition)
        
{
            
try
            
{
                DataSet ds 
= Pyllot.EC.DBUtility.MySqlHelper.ExecuteDataset(ConnectionProvider.connStringMySql, CommandType.Text, "select * from Categories where CategoryName='" + strCondition+"'");
                ds.Tables[
0].TableName = "bbooks";
                
return ds.Tables[0];
            }

            
catch (Exception exc)
            
{
                
throw exc;
            }

        }


        
//测试数据
        public CategoriesData GetCategory(string categoryId)
        
{
            CategoriesData category 
= null;
            
return category;
        }


        
// 插入数据Insert 返回bool
        public bool Insert(CategoriesData data)
        
{
            
try
            
{
                
Populate Parameters

                Pyllot.EC.DBUtility.MySqlHelper.ExecuteNonQuery(ConnectionProvider.connStringMySql, CommandType.Text, 
"insert into Categories values(?CategoryID,?CategoryName,?Description)", arParams);
                
return true;
            }

            
catch (Exception exc)
            
{
                
throw exc;
            }

        }


        
//更新数据,返回bool
        public bool Update(CategoriesData data)
        
{
            
try
            
{
                
Populate Parameters

                Pyllot.EC.DBUtility.MySqlHelper.ExecuteNonQuery(ConnectionProvider.connStringMySql, CommandType.Text, 
"update Categories set CategoryName=?CategoryName,Description=?Description where CategoryID=?CategoryID", arParams);
                
return true;
            }

            
catch (Exception exc)
            
{
                
throw exc;
            }

        }


        
public bool Delete(int CategoryID)
        
{
            
try
            
{
                
Populate Parameters

                Pyllot.EC.DBUtility.MySqlHelper.ExecuteNonQuery(ConnectionProvider.connStringMySql, CommandType.Text, 
"delete from Categories where CategoryID=?CategoryID", arParams);
                
return true;
            }

            
catch (Exception exc)
            
{
                
throw exc;
            }

        }

    }

}

 

那么,为什么我们要实现接口ICategory呢?原因有三:

 其一,这些业务逻辑即为基本的数据库操作,包括Select,Insert,Update和Delete。由于这些业务逻辑对象,仅具有行为而与数据无关,因此它们均被抽象为一个单独的接口模块IDAL,例如数据表Category对应的接口ICategory;

其次,它体现了“抽象”的精神,或者说是“面向接口编程”的最佳体现。抽象的接口模块IDAL,与具体的数据库访问实现完全隔离。这种与实现无关的设计,保证了系统的可扩展性,同时也保证了数据库的可移植性。可以支持SQL Server和mysql,那么它们具体的实现就分别放在两个不同的模块SQLServerDAL、mysqlDAL中。

其三,具体一点讲,在SQLServerDAL、mysqlDAL中都具有类Category,如果业务逻辑层要调用dal时,到底调用哪个类库中的Category呢?如果我们将类的共性抽象出来形成接口时,那么外界仅需要与接口打交道即可。

3.建立类库Pyllot.EC.IDAL,当然从步骤二的原理,我们完全可以想像出此类库下面的类只是规范了每个类的基本行为,例如Category,我们可以得出代码如下:

 

 

using System;
using System.Collections.Generic;
using System.Text;
using Pyllot.EC.Cargo.Model;
using System.Data;

namespace Pyllot.EC.Cargo.IDAL
{
    
public interface ICategory
    
{
        DataSet GetAll();
        DataTable SelectByCondition(
string strCondition);
        CategoriesData GetCategory(
string categoryId);
        
bool Insert(CategoriesData data);
        
bool Update(CategoriesData data);
        
bool Delete(int CategoryID);
    }

}

4.考虑到业务逻辑层与数据访问层的数据对象传递问题,所以我们有必要建一个类库Pyllot.EC.Model,用来放一些数据实体,对应数据库中相应的数据表。它们没有行为,仅用于表现对象的数据。这些实体类都被放到Model程序集中,例如数据表Category对应的实体类CategorieData,其代码格式如下:

 

using System;
using System.Collections.Generic;
using System.Text;

namespace Pyllot.EC.Cargo.Model
{
    
public class CategoriesData
    
{
        
Private Fields


        
Constructor

        
Public Properties
    }

}

 

 

 

 

 5.现在我们已经有了数据实体,数据对象的抽象接口和实现,可以说有关数据库访问的主体就已经完成了。留待我们的还有两个问题需要解决:
1、数据对象创建的管理。
2、利于数据库的移植。

项目紧,下次见。

 

 

 

posted on 2009-02-23 23:50  jasonM  阅读(796)  评论(1编辑  收藏  举报