机房重构-七层登录

 前期准备:

     1.画图

    通过画包图将各个层之间的关系更加详细的展示出来。除了D层与接口层之间是实现关系,其他包之间都是依赖关系。在以后的代码编写过程中的逻辑也会更加明确

      

七层是什么?

  1. 实体层(Entity):主要是用来封装一些功能性代码,定义实体类型和实体集合,用于各层次传递参数用来存放用户输入的信息。
  2. 数据访问层(DAL):提供基本的数据访问,该层将有关数据库的操作放在单独的一个类中,针对数据的增删改查
  3. 接口层(IDAL):定义一个统一的接口,解除B层与D层的耦合
  4. 工厂层(Factory):登录中用到的是抽象工厂+反射+配置文件。灵活的实现了数据库的连接,提高了代码的灵活性
  5. 业务逻辑层(BLL):负责处理业务逻辑
  6. 外观层(Facade):此处运用了外观模式,层与层之间不直接产生联系,解除了B层与U层之间的耦合。
  7. 表示层(UI):只负责显示和采集用户操作,不包含任何的业务相关的逻辑处理。

代码展示

一.实体层 Entity,实体层目的是创建一个公共信息的访问站,它与数据库中的数据表数据相对应,用来存放用户输入的信息。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Entity
{
    public class UserInfo
    {
        //定义用户ID字段
        private string userid;
        public string UserID
        {
            get { return userid; }
            set { userid = value; }
        }


        //定义 密码字段
        private string password;
        public string Password
        {
            get { return password; }
            set { password = value; }
        }


    }
}

IDAL层:定义D层统一的接口方法,实现D层各个功能,创建就是一个接口,具体的功能靠D层实现。

namespace IDAL
{
    public interface LoginIDAL
    {
        DataTable selectUser(Entity.UserInfo userInfo);
    }
}

三、DAL层:实现IDAL层中的方法,访问数据库中的数据,对数据进行一定的操作(增删改查)。

namespace DAL
{
    public class LoginDAL:IDAL.LoginIDAL
    {
        public DataTable selectUser(Entity.UserInfo UserInfo)         //selectUser该方法即是IDAL接口的方法
        {
            SQLHelper SQLHelper = new SQLHelper();                    //实例化    跳转到SQLHelpe层

            //声明一个SQL参数的数组  params可变数组
            SqlParameter[] sqlParams = { new SqlParameter("@txtUserID", UserInfo.UserID), new SqlParameter("@txtPWD", UserInfo.Password) };    //用户名和密码

            string sql = @"SELECT *FROM User_Info WHERE UserID=@txtUserID and PWD =@txtPWD and state='True'";  //查的语句 用户名 和 密码相等 并且状态为True

            DataTable table = SQLHelper.ExecuteQuery (sql, sqlParams, CommandType.Text);

            return table;

        }

    }
}

同时我们在DAL层会封装一个的sqlHelper,目的是连接数据库实现对数据库的增删改查的操作。存在目的是为了服务于DAL

namespace DAL
{
    public class SQLHelper
    {
        #region  构造函数

        private SqlConnection conn = null;       //SqlConnection 打开连接
        private SqlCommand cmd = null;          //SqlCommand对象允许你指定在数据库上执行的操作的类型。比如,你能够对数据库中的行数据执行select,insert,modify以及delete命令。
                                                //SqlCommand对象能被用来支持断开连接数据管理的情况,可以只单独使用SqlCommand对象。也可以与SqlDataAdapter一起实现断开数据连接,实现操作数据库的应用程序
        private SqlDataReader sdr = null;        //读取只进的行流的方式

        public SQLHelper()
        {
            string connStr = ConfigurationManager.AppSettings["connStr"];     //ConnStr 是配置文件里连接数据库的关键字,引用这一句可以连接数据库
            conn = new SqlConnection(connStr);   //实例化一个连接
        }

        #endregion


        #region SQL连接打开
        private SqlConnection GetConn()
        {
            if (conn.State == ConnectionState.Closed)     //如果连接状态为关闭 
            {
                conn.Open();     //则打开
            }
            return conn;
        }
        #endregion

        #region   非存储过程

        /// <summary>
        /// 执行不带参数的的   增删改   SQL语句或者存储过程
        /// </summary>
        /// <param name="cmdText">增删改SQL</param>
        /// <param name="ct">命令类型</param>
        /// <returns>返回受影响的行数</returns>
        public int ExecuteNonQuery(string cmdText, CommandType ct)
        //增删改 SQL   命令类型
        {
            int res;
            try
            {
                cmd = new SqlCommand(cmdText, GetConn());     //打开连接
                cmd.CommandType = ct;
                res = cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {
                if (conn.State == ConnectionState.Open)
                {
                    conn.Close();     //关闭数据库 与上面相对应
                }

            }
            return res;
        }

        /// <summary>
        /// 执行带参数的的   增删改   SQL语句或者存储过程
        /// </summary>
        /// <param name="cmdText">增删改SQL</param>
        /// <param name="paras">要查询的参数</param>
        /// <param name="ct">命令类型</param>
        /// <returns>返回受影响的行数</returns>
        public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct)
        {
            int res;
            using (cmd = new SqlCommand(cmdText, GetConn()))     //使用using,可以自动关闭数据库
            {
                cmd.CommandType = ct;
                cmd.Parameters.AddRange(paras);
                res = cmd.ExecuteNonQuery();
            }
            return res;
        }


        /// <summary>
        ///  执行不带参数的   查询   SQL语句或存储过程
        /// </summary>
        /// <param name="cmdText">查询SQL语句或存储过程</param>
        /// <param name="ct">命令类型</param>
        /// <returns></returns>
        public DataTable ExecuteQuery(string cmdText, CommandType ct)
        {
            DataTable dt = new DataTable();
            cmd = new SqlCommand(cmdText, GetConn());
            cmd.CommandType = ct;
            using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                dt.Load(sdr);
            }
            return dt;
        }


        /// <summary>
        /// 执行带参数的   查询   SQL语句或存储过程
        /// </summary>
        /// <param name="cmdText">查询SQL语句或存储过程</param>
        /// <param name="paras">参数集合</param>
        /// <param name="ct">命令类型</param>
        /// <returns></returns>
        public DataTable ExecuteQuery(string cmdText, SqlParameter[] paras, CommandType ct)
        {
            DataTable dt = new DataTable();
            cmd = new SqlCommand(cmdText, GetConn());

            cmd.CommandType = ct;
            cmd.Parameters.AddRange(paras);
            using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                dt.Load(sdr);
            }
            return dt;
        }

        #endregion
    }
}

D层的返回来的信息如何传回到B层呢?

四、Factory(工厂层):定义一个接口层,实现BLL层与DAL层之间的数据传递。工厂层用到了抽象工厂+反射+配置文件,实现了不同数据库之间的连接。反射+配置文件的最大作用在更方便的更改不同数据库的连接。

工厂+反射+配置文件

反射:最大的有点就是用字符串代表数据库,更改字符,就可以更换数据库。

namespace Factory
{
    public class LoginFactory
    {
        string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"];    //接收来自配置文件的数据

        public IDAL.LoginIDAL CreateUser()
        {
            string ClassName = StrDB + "." + "LoginDAL";   //这里的LoginDAL是D层的类名

            return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);   //反射加工厂的应用
        }
    }
}

五、BLL层:执行特定的业务逻辑。

登陆界面BLL层:1.对D层返回来的信息进行判断,用户是否存在的问题,2.如果存在还会产生,返回更加具体的信息给U层

namespace BLL
{
    public class loginBLL
    {
        public bool UserBLL(Entity.UserInfo UserInfo)
        {
            Factory.LoginFactory fact = new Factory.LoginFactory();     //实例化工厂 跳转到Fac 层 接收配置文件的数据,接收完成之后再回来

            IDAL.LoginIDAL idal = fact.CreateUser();      //调用工厂放发创建接口  跳转Factory层使用CreateUser的方法

            DataTable table = idal.selectUser(UserInfo);  //接收D层的返回值   跳转到DAL层

            bool flag;
            if (table.Rows.Count == 0)                    //返回DataTable类型,如果他的行数等于0,说明没有符合该账户密码的用户
            {
                flag = false;
            }
            else
            {
                flag = true;
            }
            return flag;
        }
    }
}

六、Facade层,提供一个门面,一个UI层可以会访问多个BLL层,提供一个外观层,好比提供了一个简单的入口,UI层和BLL层之间的耦合度。返回B层的信息给UI层

namespace Factory
{
    public class LoginFactory
    {
        string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"];    //接收来自配置文件的数据

        public IDAL.LoginIDAL CreateUser()
        {
            string ClassName = StrDB + "." + "LoginDAL";   //这里的LoginDAL是D层的类名

            return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);   //反射加工厂的应用
        }
    }
}

七、UI层:1、提供一个登陆界面,获取用户输入的信息 2、给用户提供特定的业务功能,或者数据

namespace UI
{
    public partial class frmLogin : Form
    {
        public frmLogin()
        {
            InitializeComponent();            //跳转到Designer的InitializeComponent方法
                                              //InitializeComponent方法走完之后跳到这,跳回Programs
        }

        private void frmLogin_Load(object sender, EventArgs e)
        {
            
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            System.Environment.Exit(0);     //最彻底的退出方式,强制退出

            //this.Close();             //只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出;
            //Application.Exit();       //强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出;
            //Application.ExitThread(); //强制中止调用线程上的所有消息,同样面临其它线程无法正确退出的问题;
        }


        private void BtnOK_Click(object sender, EventArgs e)
        {
            //判断输入不能为空 
            if (txtUserID.Text.Trim() == "")
            {
                MessageBox.Show("亲,请输入用户名哦", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            if (txtPWD.Text == "")
            {
                MessageBox.Show("亲,请输入密码哦", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            Entity.UserInfo user = new Entity.UserInfo();       //实例化user

            user.UserID = txtUserID.Text.Trim(); //把在文本框中输入的东西转化为int32类型赋值给UserID
            user.Password = txtPWD.Text;    //密码赋值给Password

            Boolean flag = false; //一个布尔值,在程序中控制是否允许移动: 当鼠标左键被按下时,flag=TRUE,此时允许MouseMove事件激发,同时设定允许窗体位置随着
                                  //鼠标移动而移动;  当松开鼠标左键,那么即便鼠标移动,窗体不能随其移动而移动,所以flag=false

            Facade.loginFacade FLogin = new Facade.loginFacade();    //实例化外观 FLogin

            flag = FLogin.SelectUser(user);    //调用外观的方法,返回给user   跳到Facade层

            if (flag != false)
            {
                this.Hide();    //隐藏当前窗体
                this.DialogResult = System.Windows.Forms.DialogResult.OK;

                MessageBox.Show("登陆成功", "提示");




            }
            else
            {
                MessageBox.Show("用户名或者密码错误");
                txtUserID.Text = "";
                txtPWD.Text = "";
                txtUserID.Focus();
            }

        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42428269/article/details/106437629
今日推荐