三层架构

为什么要用三层

  说到三层,先来说一说两层结构。两层结构将界面展示、业务逻辑、数据访问等都写到一起,如果用户需求变化,就需要对整个项目进行大量修改,系统的维护和升级极其不利;而且界面层直接访问数据库,还会有安全隐患。结构如下图所示:
这里写图片描述
  所以基于两层结构的局限性,三层结构就出现了。三层结构符合“高内聚、低耦合”的特点,每个层职责明确。利用分层,降低了层间依赖,使系统的耦合更加松散,从而使系统更加容易维护和复用。
  比如:如果需求有变化,只需要更改相应的业务逻辑层;或者要改变数据库的时候,只需要将原来的数据访问层替换掉或者增加新的就可以了,而不需要牵扯到整个项目。
  三层架构虽好,但是也不是每个项目都必须采用这种结构,三层结构用于比较复杂的大型系统,如果系统比较小,则没必要将问题复杂化。

何为三层

这里写图片描述
三层由显示层(UI)、业务逻辑层(BLL)、数据访问层(DAL)组成。
1.显示层(UI)
  职责:①向用户展示特定的业务数据
     ②采集用户的信息和操作
  原则:用户至上,兼顾简洁

2.业务逻辑层(BLL)
  职责:① 从UI中获取用户指令和数据,执行业务逻辑
     ②从UI中获取用户指令和数据,通过DAL写入数据源
     ③从DAL中获取数据,以供 UI 显示用
  机制:① UI –> BLL –> UI
     ② UI –> BLL –> DAL –> BLL –> UI

3.数据访问层(DAL)
  作用:跟数据源打交道
  职责:①执行对数据的操作(增删改查)

4.数据对象层
  数据对象层包含了项目需要使用的数据对象,用数据对象来传递数据,它避免了各个层的交叉引用。
  一般一个表对应一个数据对象。

引用关系

上图已经展示了它们三者之间的引用关系。UI层–> BLL层 –> DAL层,而它们都引用数据对象层。

代码展示

下面以一个登录的小例子,展示一下三层是如何具体使用的。
UI层:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void btnLogin_Click(object sender, EventArgs e)
    {
        //获取输入的用户名和密码
        string userName = txtUserName.Text.Trim();
        string userPassword = txtPassword.Text;

        Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();
        //调用B层的登录方法,从B层返回user的信息
        UserInfo user = mgr.Login(userName, userPassword);

        MessageBox.Show("登录用户:" + user.UserName);
    }
}

BLL层:

public class LoginManager
{
    public UserInfo Login(string userName,string password)
    {
        //实例化UserDao
        UserDAO uDao = new UserDAO();
        //调用UserDao的查询用户方法
        UserInfo user = uDao.SelectUser(userName, password);

        //如果用户存在,就调用ScoreDao的更新积分方法,给用户加10积分;否则就抛出异常
        if (user != null)
        {
            ScoreDAO sDao = new ScoreDAO();
            //调用ScoreDao的更新积分方法
            sDao.UpdateScore(userName, 10);
            return user;
        }
        else
        {
            throw new Exception("登录失败。");
        }
    }
}

DAL层:

public class UserDAO
{
    /// <summary>
    /// 查询用户是否存在并返回用户信息
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="password">密码</param>
    /// <returns></returns>
    public UserInfo SelectUser(string userName,string password)
    {
        using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
        {
            SqlCommand cmd = conn.CreateCommand();

            //获取执行的SQL语句 或表名 或存储过程名
            cmd.CommandText = @"SELECT ID,UserName,Password,Email
                                FROM USERS WHERE UserName=@UserName AND Password=@Password";
            //指示执行的是存储过程还是sql语句,默认执行语句
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Add(new SqlParameter("@UserName", userName));
            cmd.Parameters.Add(new SqlParameter("@Password", password));

            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();

            UserInfo user = null;
            while (reader.Read())
            {
                if (user == null)
                {
                    user = new UserInfo();
                }
                user.ID = reader.GetInt32(0);
                user.UserName = reader.GetString(1);
                user.Password = reader.GetString(2);
                if (!reader.IsDBNull(3))
                {
                    user.Email = reader.GetString(3);
                }
            }
            return user;
        }
    }
}
public class ScoreDAO
{
    /// <summary>
    /// 更新用户积分
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="value">要增长的积分</param>
    public void UpdateScore(string userName,int value)
    {
        using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
        {
            SqlCommand cmd = conn.CreateCommand();

            //查询Scores表中是否已有用户信息
            cmd.CommandText = @"SELECT * FROM Scores WHERE UserName =@UserName";                
            cmd.CommandType = System.Data.CommandType.Text;
            cmd.Parameters.Add(new SqlParameter("@UserName", userName));
            cmd.Parameters.Add(new SqlParameter("@Score", value));

            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();                

            //如果Scores表中用户积分已存在就在原来的基础上加10份;否则就插入新的用户积分数据
            if (reader.Read())
            {
                //在用户原有积分基础上加10分
                cmd.CommandText = @"UPDATE Scores SET Score+=10 WHERE UserName = @UserName";
                //关闭reader
                reader.Close();
                //执行SQL语句
                cmd.ExecuteNonQuery();
            }
            else
            {
                reader.Close();
                //插入新的用户积分数据
                cmd.CommandText = @"INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)";
                cmd.ExecuteNonQuery();
            }
        }                        
    }
}
  • 16
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值