.NET三层架构

来源:互联网 发布:网络歌手小右照片 编辑:程序博客网 时间:2024/06/02 14:53

零基础学C#3.0 -- .net的三层架构 - CodingPenguin
时间 2014-01-26 17:40:00 博客园-所有随笔区
原文  http://www.cnblogs.com/codingpenguin/p/3534304.html
主题 .Net 数据库
新手学C# ——.net的三层架构之最简单实例:登录界面
三层架构包括:
1. 数据访问层(Data Access Layer, DAL):负责将底层数据传送到业务逻辑层
2. 业务逻辑层(Business Logic Layer, BLL):处理数据访问层传送的数据,并实现业务逻辑
3. 表示层(User Interface, UI):不处理任何业务,负责显示与实时更新
其中1--2--3层次依次上升。
为了使信息能够顺利由底层传送,可以采用实体类的方法,添加实体层。实体类通常与数据库中字段相互对应,拥有get和set属性。实体类的目的是用于替代DataSet,通过类的方式传递数据,并使逻辑更加清晰。
三层架构来源于MVC,其核心思想是保持三层之间的相互独立,在对其他功能进行局部修改时,可以使三层结构保持大体不变,以免进行全局的修改。换句话说,在修改某局部代码后,你自然而然的知道 何处的代码应该进行修改 , 何处的代码可以不进行修改 , 如何规范修改的局部代码对上层的接口以达到减少修改量的目的 。
这里不得不说的是,在三层架构中,修改局部代码对整体的变动还是很大的,层次数越多,需要修改的部分越少。当然,层次数的增加伴随着逻辑的复杂性增加和接口的复杂性增加。越是小型的项目,需要的层次数越少。
下面举一个最简单的例子:用户登录。
数据库中表Login的结构:
LoginID : 用户名
LoginPwd : 用户密码
(1)新建一个WinForm项目SchoolManager,在项目解决方案中点击右键新建三个类库(SchoolManager.DAL, SchoolManager.BLL, SchoolManager.Model),分别表示数据访问层、业务逻辑层和实体层。
(2)右键单击类库,添加引用(BLL引用DAL,UI引用BLL,三者都引用Model),表达四者之间的逻辑依赖关系。这里强调的是,UI不引用DAL。
(3)编写实体类Login.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SchoolManager.Model
{
    public class Login
    {
        private int stuID;  //学号
        public int StuID
        {
            get { return stuID; }
            set { stuID = value; }
        }

        private string studentName;  //姓名
        public string StudentName
        {
            get { return studentName; }
            set { studentName = value; }
        }

        private string loginID;  //登录名
        public string LoginID
        {
            get { return loginID; }
            set { loginID = value; }
        }

        private string loginPwd;  //登录密码
        public string LoginPwd
        {
            get { return loginPwd; }
            set { loginPwd = value; }
        }

        private int state;
        public int State
        {
            get { return state; }
            set { state = value; }
        }

    }
}这个实体类与数据库中的表一一对应(这里没有对应的原因是实际程序中只用到了两个字段,实际数据库中的表以此类中的字段为准),也就是说,数据库中表的每一行都可以转化为这个类中的一个实例,从而在各个层中传递数据。
(4)编写DAL类LoginService.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchoolManager.Model;
using System.Data.SqlClient;

namespace SchoolManager.DAL
{
    public static class LoginService
    {
        static string connStr = @"Data Source=(local)\SQLEXPRESS;Initial Catalog=StudentInfo;Integrated Security=True;Pooling=False";
        private static SqlConnection sqlConn = new SqlConnection(connStr);

        /// <summary>
        /// 根据登录名返回用户类
        /// </summary>
        /// <param name="loginID">登录名</param>
        /// <returns>用户类</returns>
        public static Login GetLoginByLoginID(string loginID)
        {
            string sql = "select * from Login where LoginID='" + loginID + "'";
            try
            {
                SqlCommand sqlCmd = new SqlCommand(sql, sqlConn);
                sqlConn.Open();
                SqlDataReader sqlReader = sqlCmd.ExecuteReader();
                if (sqlReader.Read())
                {
                    Login user = new Login();
                    user.LoginID = Convert.ToString(sqlReader["LoginID"]);
                    user.LoginPwd = Convert.ToString(sqlReader["LoginPwd"]);
                    user.State = Convert.ToInt32(sqlReader["State"]);
                    user.StudentName = Convert.ToString(sqlReader["StudentName"]);
                    user.StuID = Convert.ToInt32(sqlReader["StuID"]);
                    sqlReader.Close();
                    sqlConn.Close();
                    return user;
                }
                else
                {
                    sqlConn.Close();
                    sqlReader.Close();
                    return null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw ex;
            }
        }
    }
}这里注意几点:
a)此类(以及之后的BLL,UI)引入了Model的命名空间,从而可以调用Model中的Login类并生成实例,这正是添加引用的原因所在。
b)此类引入了System.Data.SqlClient,也是这三层中唯一引用这个命名空间的层,即所有对数据库的操作都要在这一层的不同类中完成。
c)GetLoginByLoginIn()方法的返回值是Login类的一个实例,实质上是返回查询后的指定行数据。
(5)编写BLL类LoginManager.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchoolManager.Model;
using SchoolManager.DAL;

namespace SchoolManager.BLL
{
    public class LoginManager
    {
        /// <summary>
        /// 从数据访问层调用数据的方法
        /// </summary>
        /// <param name="loginID">登录名</param>
        /// <returns>密码是否匹配</returns>
        public static bool GetLogin(string loginID, string loginPwd)
        {
            Login user = LoginService.GetLoginByLoginID(loginID);
            if (user.LoginPwd == loginPwd)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    }
}注意以下几点:
a)引用了DAL的命名空间,因为要调用DAL中的GetLoginByLoginIn()方法。
b)GetLogin()实际上已经完成了用户登录的逻辑功能,不能将判断式写入UI层中。
(6)编写UI层LoginForm.cs:(界面很简洁,用户名、密码输入框,确定、取消按钮)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SchoolManager.Model;
using SchoolManager.BLL;

namespace SchoolManager
{
    public partial class LoginForm : Form
    {
        public LoginForm()
        {
            InitializeComponent();
        }

        private void buttonLogin_Click(object sender, EventArgs e)
        {
            //检测用户名是否为空
            if(string.IsNullOrEmpty(textBoxName.Text))
            {
                MessageBox.Show("请输入用户名");
                return;
            }

            //检测密码是否为空
            if (string.IsNullOrEmpty(textBoxPwd.Text))
            {
                MessageBox.Show("请输入密码");
                return;
            }

            //调用业务逻辑层方法登录
            if(LoginManager.GetLogin(textBoxName.Text, textBoxPwd.Text))
            {
                MessageBox.Show("登陆成功");
            }
            else
            {
                MessageBox.Show("用户名或密码错误");
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}这里有几点需要注意:
a)引用命名空间(详见上文)
b)对TextBox中是否为空的判断可以由UI层完成,也可以在BLL层中编写Validate()函数并在UI层中调用,不过还是建议在UI层中完成,毕竟界面的修改必然伴随着Validate()方法的修改
c)UI层调用GetLogin()方法之后,只是将返回的布尔值解释为登录成功/失败,没有进行逻辑上的判断。
希望本文能对.net学习的菜鸟级新手有所帮助!(本人也处于这一行列)

 

0 0