【C#】之七层登录代码详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/molihuakai_118/article/details/84146215

前言

  之前我有写过一篇三层登录,应用三层,将界面处理、业务逻辑处理和数据访问分别开来,能够很好的减少登录系统中各个模块之间的耦合度,使的系统更加可维护、可复用和可扩展。而七层登录是在三层基础之上的更完美的改进,他除了主三层中有的UI层、BLL层、DAL层和Enitity层(实体层)之外,还引入了Facade层(外观层)、IDAL层(接口层)、Factory层(工厂层)和SQLHelper类,使得三层更加独立封闭,充分体现了面向对象编程。下面我们就来具体看一下七层到底是怎样实现的。

一、新增加的层?

1、 Facade层(外观层)

  外观层应用了设计模式中的外观模式(为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用),在七层中,它位于UI层与BLL层之间,在BLL层中可能有多可业务逻辑类,这些业务逻辑类被UI层调用,在没有外观层时,UI层每需要一个业务逻辑类就要实例化一个,带有耦合性,扩展起来很不方便。应用外观层之后,UI层直接将数据传入外观的某个方法中,由外观去实例化业务逻辑类,这样扩展的时候直接改变UI与外观之间的链接就可以了,不需要对业务逻辑在进行处理,进一步减少了UI层与BLL层之间的耦合性。

2、Factory层(工厂层)

  工厂层应用了设计模式中的抽象工厂模式(提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类),它位于BLL层与DAL层之间,在工厂层中应用了反射+配置文件的数据访问程序,由于BLL层可能要访问多个DAL中的具体类,通过配置文件连接BLL层要访问的具体程序集(即DAL层),通过反射,反射出来BLL层要访问的DAL层中的具体类,这样就减少了BLL层与DAL层中相互依赖对象之间的耦合,直接由工厂去指定具体的类。

3、IDAL层(接口层)

  接口层的应用充分实现了接口隔离远原则,它位于BLL层与DAL层之间,BLL层与DAL层中的类没有必要直接通信,当BLL层中的一个类需要调用DAL层中一个类的方法时,可以通过接口IDAL来转发这个调用。

4、SQLHelper类

  这一层没有单独的命名空间,可以将它看做是DAL层中的一个辅助类,我们直接将它放在了DAL层,他的存在完全是为了减轻DAL层的负担,我们知道DAL层是数据访问层,所有参与数据库的操作(连接、增、删、改、查)都要放在其中,为了避免DAL层中每一个类都重复这些操作,我们就可以将对数据库的具体操作单独的封装在一个SQLHelper类当中,作为一个模块存在,DAL中的其他类提出对数据库的操作后,将操作要求传入SQLHelper模块中,将结果在返回给提出要求的这个类。这样一来减少的代码的冗余,利于编程。

二、图解

在这里插入图片描述
  我们在分析的时候,是按照数据流动的情况进行分析的,即UI——>Facade——>BLL——>Factory——>IDAL——>DAL——>SQLHelper,但是数据是贯穿于整个七层的,为了避免敲代码是后所引用的方法爆红(前提是现将类都建好并命好名),我们在敲代码的时候的顺序与分析的顺序不一致,即Enitity——》IDAL——》DAL——》Factory——》BLL——》Facade——》UI,这样只是为了方便书写,当然,如果敲起来不顺手的话,还可以从头向后敲,每用到一个方法就去写一个方法框架。

三、代码详解

  按照我们分析的过程进行代码详解。

Enitity层

namespace Enitity
{
    //实体层
    public class UserInfo
    {
        //定义用户ID属性    
        private int userid;
        public int UserID
        {
            get { return userid; }
            set { userid = value; }
        }

        //定义用户密码PassWord属性 
        private string  password;
        public string PassWord
        {
          get { return password; }
          set { password = value; }
        }

    }

UI层

private void BtnLogin_Click(object sender, EventArgs e)
        {
            //判断输入不能为空
            if (TxtID.Text.Trim() == "")
            {
                MessageBox.Show("请输入用户名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            if (TxtPassword.Text == "")
            {
                MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            try
            {
                //实例化一个用户实体user
                Enitity.UserInfo user = new Enitity.UserInfo();

                //接收控件传来的用户信息
                user.UserID = Convert .ToInt32(TxtID.Text.Trim());
                //接收控件传来的密码信息
                user.PassWord = TxtPassword.Text;

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

                //定义一个bool型的变量,用来接收是否查找成功
                Boolean flag = false;

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

                //判断是否登录成功
                if (flag != false)
                {
                    MessageBox.Show("登录成功!");
                    this.Hide();

                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                    //实例化一个窗体
                    Form a = new Form();
                    a.Show();
                }
                else
                {
                    MessageBox.Show("用户名或密码错误!");
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


    

Facade层

namespace Facade
{
    //外观层
    public class LoginFacade
    {
        //将数据user从UI层传入BLL层,提供返回值给flag
        public Boolean SelectUser(Enitity.UserInfo user )
        {       
            bool flag;

            //实例化一个B层
            BLL.LoginBLL userBLL = new BLL.LoginBLL();

            //将用户数据传入B层,返回值给flag
            flag = userBLL.UserBLL(user);

            return flag;
        }      
    }
}

BLL层

namespace BLL
{
    //业务逻辑层
    public class LoginBLL
    {
        //判断用户是否存在
        public bool UserBLL(Enitity.UserInfo user)
        {
            //实例化工厂
            Factory.LoginFactory fact = new Factory.LoginFactory();

            //调用工厂中的方法,实例化一个实现接口的内部类,将反射结果赋给idal
            IDAL.LoginIDAL idal = fact.CreateUser();//登录中,此时的idal反射的是dal中的LoginDAL类

            //接收D层的返回值
            DataTable table = idal.SelectUser(user);            

            bool flag;

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

            //返回数值
            return flag;
        }
    }
}

Factory层

namespace Factory
{
    //工厂层
    public class LoginFactory
    {
        //接收来自配置文件的数据,明确工厂要链接那一层
        string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"];
        
        //应用反射来获取被调用的DAL层的具体操作类
        public IDAL.LoginIDAL CreateUser()
        {   
            //明确具体操作类
            string ClassName = StrDB + "." + "LoginDAL";

            //反射加工厂的应用——将在DAL层中用到的具体类反射到接口,说明那个类实现了这个接口
            return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);

        }
    }
}

IDAL层

namespace IDAL
{
    public interface LoginIDAL
    {     
            //放置接口函数,判断要登录的用户是否在数据表中存在
            DataTable SelectUser(Enitity.UserInfo user);   
    }
}

DAL层

namespace DAL
{
    public class LoginDAL:IDAL.LoginIDAL
    {
        public DataTable SelectUser(Enitity.UserInfo user)
        {
            //实例化数据操作类,进行数据查询,并获取返回值
            SQLHelper sqlHelper = new SQLHelper();

            //选择要查询的数据类型,作为sqlCommand的参数
            SqlParameter[] sqlparams = {new SqlParameter ("@ID",user.UserID),
                                        new SqlParameter("@Password",user.PassWord )};

            //查询语句
            string sql = "select * from Users where ID =@ID AND Password=@Password";

            //将查询语句和要查询的数据 传入sqlHelper类中进行查询操作
            DataTable table = sqlHelper.ExecuteQuery(sql,sqlparams,CommandType.Text);//CommandType.Text解释SQL文本命令的字符串

            return table;
        }
    }
}

SQLHelper类

namespace DAL
{
    //数据访问层——数据操作类
    public class SQLHelper
    {        
        private SqlConnection conn = null;//定义数据连接操作
        private SqlCommand cmd = null;  //指定能在数据库上执行的操作
        private SqlDataReader sdr = null; //定义一个读取数据流的变量,从数据库中只读

        /// <summary>
        /// 数据库连接
        /// </summary>
        public SQLHelper()//构造函数
        {
            string connStr = ConfigurationManager.AppSettings["connStr"];//ConnStr配置文件中连接数据库的关键字(字符串)
           conn = new SqlConnection(connStr); //实例化一个连接
        }

        //将连接的数据库打开
        private SqlConnection GetConn()
        {
            if (conn.State == ConnectionState.Closed )//如果连接状态为关闭,则打开
            {
                conn.Open();
            }
            return conn;
        }
        
//只显示运行代码,SQLHelper类中的其他数据库操作省略

 	/// <summary>
        /// 执行带参数的SQL查询语句或存储过程
        /// </summary>
        /// <param name="cmdText"></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 ());//cmdText为传进来的SQL命令,GetConn为一个打开状态的数据库连接

            cmd.CommandType = ct;
            cmd.Parameters .AddRange (paras);//将要查询的数据放入查询语句中

            //cmd.ExecuteReader读取结果集中的数据,将完整的数据发送到connection,生成sqlDataReader赋给sdr。
            //括号中表明当关闭sqlDataReader时,关联的connection也会关闭。
            using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                //通过提供的sqlDataReader,对表进行操作
                dt.Load(sdr);
            }
            return dt;
        }
    }
}

结:对于七层登录,一定要理清他的逻辑思路,层与层之间的关系以及代码的执行过程,敲完之后多跑几遍,对于不懂得方法充分利用好ArcObjects帮助文档,里面的解释非常详细(还要感谢帅行的帮助,万分感谢!)

猜你喜欢

转载自blog.csdn.net/molihuakai_118/article/details/84146215
今日推荐