【C#】机房重构——七层登录

  前言:


      两个多星期的探索终于算是把登录敲通了,当“登录成功!”显示在我眼前的那一刻,我想那种快乐的感觉就好像我中了三百万大奖一样的激动吧! 三层当时不是很明白,所以三层到七层走了不少弯路。出来混早晚是要还的,这话说的一点都没错。废话不多说了,直接上料。



何为七层?

        这里的七层是在三层的基础上与设计模式相结合演化而来的,应用了设计模式中的外观模式和抽象工厂模式。


一、实体层(Entity):实体层,存放全局的实体类,方便各个层之前的参数调用。
二、数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、查找。无需做什么逻辑判断,只是和数据库直接交互。
三、接口层(IDAL):接口层用来定义一个统一的接口,解除B层和D层的耦合。
四、工厂层(Factory):工厂来创建接口,返回接口,用到了抽象工厂+反射+配置文件,作用是灵活的实现数据库的连接,方便换数据库,进一步解耦合。
五、业务逻辑层(BLL):主要负责一些逻辑判断和处理。
六、外观层(Facade):这里用到了外观模式,使得复杂问题简单化,用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
七:界面层(UI):主要职责是为用户提供信息,以及把用户的指令进行翻译。


包图:

        先来看看包图,一开始没有太能搞懂包图是用来干嘛的,知道后来用到引用时发现了它的妙处,这一层跟哪一层有关联啊,各个层之间有什么关系啊,通过包图一目了然。




实现步骤:


1、创建Entity,实现业务实体。 
2、创建IDAL,实现接口。 
3、创建DAL,实现接口里的方法。 
4、增加APP.config里的配置信息,为提供DAL的程序集。 
5、创建Factory,返回程序集的指定类的实例。 
6、创建BLL,调用Factory,得到程序集指定类的实例,完成数据操作方法。
7、创建Facade,调用BLL,得到BLL层的处理结果返回值。
8、创建UI,调用Facade里的数据操作方法,实现登录。 


代码实现


Entity层

 public  class UserInfo
    {
        //定义 用户ID 字段
        private int? userid;
        public int? UserID
        {
            get { return userid; }

            set { userid = value; }
        }

        //定义 用户名  字段
        private string userName;
        public string UserName
        {
            get { return userName; }
            set { userName = value; }
        }

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

        //定义 等级 字段
        private string level;
        public string Level
        {
            get { return level; }
            set { level = value; }
        }

        //定义 状态  字段
        private bool stat;
        public bool state
        {
            get { return stat; }
            set { stat = value; }
        }

    }

IDAL层

using System.Data;
 public  interface LoginIDAL
    {
       DataTable selectUser(Entity.UserInfo UserInfo);

    }


DAL层

using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace DAL
{    
   public  class LoginDAL:IDAL.LoginIDAL
    {

       public DataTable selectUser(Entity.UserInfo UserInfo)
       {
           SqlHelper sqlHelper = new SqlHelper();
           SqlParameter[] sqlParams = { new SqlParameter("@userID", UserInfo.UserID), new SqlParameter("@PassWord", UserInfo.PassWord) };
           string sql = @"SELECT * FROM [User_Info] WHERE UserID=@UserID and PWD =@PassWord";
           DataTable table = sqlHelper.ExecuteNonQuery(sql,sqlParams,CommandType.Text);
           return table;
       }  

    }
}

SQLHelper类

using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace DAL
{
    public class SQLHelper
    {
        private SqlConnection conn = null;
        private SqlCommand cmd = null;
        private SqlDataReader sdr = null;

        public SQLHelper()
        {
            string connStr = ConfigurationManager.AppSettings["connStr"];
            conn = new SqlConnection(connStr);
        }

        private SqlConnection GetConn()
        {
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }
            return conn;
        }


        /// <summary>
        /// 执行不带参数的的增删改SQL语句或者存储过程
        /// </summary>
        /// <param name="cmdText">增删改查SQL</param>
        /// <param name="ct">命令类型</param>
        /// <returns>返回受影响的行数</returns>
        public int ExecuteNonQuery(string cmdText,CommandType ct)
        {
            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()))
            {
               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;
        }
    }
}


配置文件:

在APP.config这个文件里添加下面的代码;

 <appSettings>
    <add key ="ConnStr" value="server=.; database=LCS;user ID = sa ; pwd=123456"/>  <!-- server是自己数据库的名字或者用.代表本地;把database,uid,pwd修改为与自己数据库对应的关系-->
    <add key ="DB" value="DAL" />
  </appSettings>


Factory层

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

        public IDAL.LoginIDAL CreateUser()
        {
            string ClassName = StrDB + "." + "LoginDAL";//DAL层的类名  
            return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);  //反射加工厂的应用            
        }
    }


BLL层

 public class LoginBLL
    {
       public bool UserBLL(Entity.UserInfo UserInfo)
       {
           Factory.LoginFactory fact = new Factory.LoginFactory();//实例化工厂
           IDAL.LoginIDAL idal = fact.CreateUser();//调用工厂方法创建接口  
           DataTable table = idal.selectUser(UserInfo);//接受D层的返回值  
           bool flag;
           if (table.Rows.Count == 0)//返回的DataTable类型,如果它的行数等于0,说明没有符合该帐号密码的用户  
           { flag = false; }
           else
           {
               flag = true;
           }
           return flag;
       }
    }


Facade层

  public class LoginFacade
    {
        public Boolean SelectUser(Entity.UserInfo user)
        {
            bool flag;
            BLL.LoginBLL userBLL = new BLL.LoginBLL();
            flag = userBLL.UserBLL(user);
            return flag;
        }
    }

UI层

namespace UI
{

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

        private void lblLogin_Click(object sender, EventArgs e)
        {


            //判断输入不能为空
            if (txtUserID.Text.Trim() == "")
            {
                MessageBox.Show("哎呀!忘记写用户名了~", "小妖提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            if (txtPWD.Text == "")
            {
                MessageBox.Show("你个大迷糊,快去写密码!", "小妖提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }


            try
            {

                Facade.LoginFacade Facade = new Facade.LoginFacade();
                Entity.UserInfo user = new Entity.UserInfo();
                user.UserID = Convert.ToInt32(txtUserID.Text.Trim());
                user.PassWord = txtPWD.Text;


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


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

                if (flag != false)
                {
                    this.Hide();                     //隐藏当前窗体
                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                    frmMian frmMian = new frmMian();//实例化一个窗体
                    frmMian.Show();                 //显示实例化的窗体
                }
                else
                {
                    MessageBox.Show("密码或者用户名错误");
                }

            }
            catch (Exception)
            {
                throw;
            }
        }

        private void lblCancel_Click(object sender, EventArgs e)
        {

            System.Environment.Exit(0); //这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。


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


最后又由代码生成的图如下,和包图大致相同;



总结:

            这次重构采用了分层思想,使得耦合度大大降低,实现了代码良好的扩展性,且便于维护和修改代码.尽管这个过程很是磨人,但最终还是走出来了,万事开头难,加油!


评论 61
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值