浅谈C#数据库业务的分层架构与实例解析

时间:2024-03-14 18:47:11

一.前言

        假设有这么一个需求:从连接某个数据库并从中查询某个表的信息,放到程序的位置进行存储。

        想必一开始的写法会是下面这样:

#region 根据数据库添加内容
        public void FillGridView(DataGridView MyGrid, string Upname, int Count)
        {
            //新建命令
            SqlCommand com = new SqlCommand();
            com.Connection = MyConnection;
            com.CommandType = CommandType.Text;

            //sql语句
            com.CommandText = "select * from TAB_ACCESS where ACCESS_LEVEL=1 AND ACCESS_NAME='" + Upname + "'";

            //执行语句
            SqlDataReader reader = com.ExecuteReader();
            string name = null;
            string score = null;
            //读取数据
            while (reader.Read())
            {
                name = reader["ACCESS_NAME"].ToString();
                score = reader["ACCESS_SCORE"].ToString();
            }
            reader.Close();

            //处理读到的数据(实际业务)
            int Sum = 0;
            for (int j = 0; j < Count; j++)
            {
                Sum += RootCount[j];
                if (RootCount[j] == 0)
                    Sum++;
            }
            if (RootCount[Count] > 0)
            {
                for (int i = 0; i < RootCount[Count]; i++)
                {
                    MyGrid.Rows[Sum + i].Cells[0].Value = name;
                    MyGrid.Rows[Sum + i].Cells[1].Value = score;
                }
            }
            else
            {
                MyGrid.Rows[Sum].Cells[0].Value = name;
                MyGrid.Rows[Sum].Cells[1].Value = score;
            }
        }
        #endregion

        在这一个方法中,能完成业务的所有需求:连接数据库,读数据,处理数据。 程序能良好运行,没有什么问题。

        这时,若需要扩展新的业务,或是在后期的运维中需要修改,那么问题就出现了:方法中各自的逻辑都紧紧纠缠在一起,彼此间相互依赖,谁都是不可替换的。只能写新的方法,也就是重新完成连接数据库,读数据,处理数据的操作。这无疑加大了开发和维护的成本,效率很低。

        本着 “高内聚,低耦合” 的思想,我们要想办法降低各个业务的耦合性,连接数据库归连接数据库,读数据归读数据,处理数据归处理数据,大家进水不犯河水。于是,在项目中,我们可以考虑采用分层式架构。

 

 二.分层式架构      

最常见的分层架构为(参考百度百科描述):

1.表示层(USL - User Show Layer)

        位于最上层。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。

2.业务逻辑层(Business Logic Layer)

        业务逻辑层是系统架构中体现核心价值的部分。它的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计。

        业务逻辑层在体系架构中的位置很关键,它处于数据访问层与表示层中间,起到了数据交换中承上启下的作用。由于层是一种弱耦合结构,层与层之间的依赖是向下的,底层对于上层而言是“无知”的,改变上层的设计对于其调用的底层而言没有任何影响。如果在分层设计时,遵循了面向接口设计的思想,那么这种向下的依赖也应该是一种弱依赖关系。因而在不改变接口定义的前提下,理想的分层式架构,应该是一个支持可抽取、可替换的“抽屉”式架构。正因为如此,业务逻辑层的设计对于一个支持可扩展的架构尤为关键,因为它扮演了两个不同的角色。对于数据访问层而言,它是调用者;对于表示层而言,它却是被调用者。依赖与被依赖的关系都纠结在业务逻辑层上,如何实现依赖关系的解耦,则是除了实现业务逻辑之外留给设计师的任务。

3.数据层(DAL - Data Access Layer)

        数据访问层:有时候也称为是持久层,其功能主要是负责数据库的访问,可以访问数据库、二进制文件、文本文档或是XML文档。简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。

 

优点

1、开发人员可以只关注整个结构中的其中某一层;

2、可以很容易的用新的实现来替换原有层次的实现;

3、可以降低层与层之间的依赖;

4、有利于标准化;

5、利于各层逻辑的复用。

6、结构更加的明确

7、在后期维护的时候,极大地降低了维护成本和维护时间

缺点

1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

3、增加了开发成本。

 

三.实例解析

拿最近做的数据库项目的架构来讲,初步的分层架构如下:

浅谈C#数据库业务的分层架构与实例解析

在实际应用中的表现是这样的:

   浅谈C#数据库业务的分层架构与实例解析

Interface 为接口层。在此定义数据库访问接口。

DataModel 为数据模型层。在此定义各种类和结构体用于存储数据(在架构中可以去掉)。

DAL为数据访问层。数据库的连接以及所有对数据库的增删改查都在此实现。

BLL为业务逻辑层。读到的数据在这里进行处理,比如将存储到某个结构体或类中。

 

简单举例

假设数据库中存在一个部门表(TAB_DEPART) , 我们需要从中查询所有记录,存到预先定义好的List<DepartmentRecord>中。

操作流程如下图:

浅谈C#数据库业务的分层架构与实例解析

Interface定义:

namespace BSH_DBA.Interface
{
    /// <summary>
    /// UserDAL接口 
    /// </summary>
    public interface IUserDAL  
    {
        /// <summary>
        /// 查询所有部门记录
        /// </summary>
        /// <param name="conn">连接字段</param>
        /// <returns>DataTable:成功;其他:失败</returns>
        DataTable SelectDepartment(string conn);
    }
}

DAL中继承接口并写详细数据库操作:

namespace BSH_DBA.DAL
{
    /// <summary>
    /// 用户管理模块库数据操作
    /// </summary>
    public class UserDAL : IUserDAL
    {
        /// <summary>
        /// 查询所有部门记录
        /// </summary>
        /// <param name="conn">连接字段</param>
        /// <returns>DataTable:成功;其他:失败</returns>
        public DataTable SelectDepartment(string conn)
        {
            StringBuilder MysqlCommand = new StringBuilder();
            try
            {
                MysqlCommand.Append(string.Format(@"select * from {0}", NamedConfig.TAB_DEPART));
                DataTable dt = MySqlHelper.ExecuteDataset(conn, CommandType.Text, MysqlCommand.ToString()).Tables[0];
                return dt;
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                return null;
            }

        }
}

BAL中调用接口读到数据并存储:

namespace BSH_DBA.BLL
{
    /// <summary>
    /// 用户业务
    /// 注:用户包括服务人员、管理员、超级管理员、Admin
    /// </summary>
    public class UserBLL
    {
        private static readonly IUserDAL iUser = new UserDAL();
        /// <summary>
        /// 查询所有部门记录
        /// </summary>
        /// <param name="conn">连接字段</param>
        /// <param name="list_record">输出:部门列表</param>
        /// <returns>0:成功;其他:失败</returns>
        public static int SelectDepartment(string conn, List<DepartmentRecord> list_record)
        {
            //调用接口,读取数据
            DataTable dt = iUser.SelectDepartment(conn);
            if(dt == null)
            {
                return 1;
            }
            //遍历DataTable,将里面数据存到List中
            foreach(DataRow dr in dt.Rows)        
            {
                string id = dr["depart_id"].ToString(); 
                string name = dr["depart_name"].ToString();
                string upid = dr["depart_upid"].ToString();
                DepartmentRecord drecord = new DepartmentRecord(id,name,upid);
                list_record.Add(drecord);
            }
            return 0;
        }
    }
}



以上便是以分层架构完成的数据库业务操作。供参考。