• C# 三层架构的一个小练习(Winfrom与SQLite数据库组合)


    本文文字方面引用 微冷的風丶(博客地址:https://www.cnblogs.com/smbk/)
    代码部分是本人亲自写的一个sqlite数据库的最简单登录界面练手(当时写的太烂了,现在回顾重构一下)

    三层架构分为:表现层(UI(User Interface))、业务逻辑层(BLL(Business Logic Layer))、数据访问层(DAL(Data Access Layer))再加上实体类库(Model)

    这个例子的思路是:
    实体类库(Model)作为定义我们需要的类的空间,在实体类库(Model)我们定义的类会在UI,DAL,BLL的任意层次实例化为对象,这个对象用于临时存储变量和调用函数,用完就被垃圾收集器清理了

    DAL BLL UI三层都会引用Model类库,类库嘛,就是拿来放大家都可能使用的公共类。

    数据访问层(DAL(Data Access Layer)),有且只有Model类库被引用。作为存放数据库增删改查方法的层次,这些方法被定义在一个类中,这个类只会被BLL层实例化为对象并使用,用完就被垃圾收集器清理了
    业务逻辑层(BLL(Business Logic Layer)),有Model类库和DAL层被引用。这一层就是理清楚所需功能的逻辑,引用DAL层的各种方法,并把它们封装成BLL层的方法供UI层调用,即把DAL层写的类实例化成对象,,用完就被垃圾收集器清理了。
    表现层(UI(User Interface)),有Model类库和BLL层被引用,这一层就是制作界面之类的,使用winfrom的情况下,给按钮添加各种功能来达到想达到的效果,需要的功能从BLL层调用即可,即把BLL层写的类实例化成对象,用完就被垃圾收集器清理了。

    1、实体类库(Model),主要存放数据库中的表字段。
    操作:
    (1)先建立实体类库Model,打开项目,在解决方案中右键——>添加——>新建项目——>选中类库——>改名Model——>确定

    (2)选中Model类库——>建立实体类命名为:UserInfo

        public class UserInfo
        {
            //以下字段用来存储
            public string UserAccount { get; set; }//注册时的用户名,还可以做查询返回字段使用
            public string UserPassword { get; set; }//注册时的密码,还可以做查询返回字段使用
            public string UserPasswordConfirm { get; set; }//注册时的确认密码(仅做此作用)
    
            public string InputAccount { get; set; }//用户输入的用户名(非第一次注册)
            public string InputPassword { get; set; }//用户输入的密码(非第一次注册)
            public string PasswordInDB { get; set; }//返回时用到的数据库中存储的密码
            public string ChangePassword { get; set; }//用户修改密码时输入的密码
        }
    

    2、数据访问层(DAL),主要是存放对数据类的访问,即对数据库的添加、删除、修改、更新等基本操作
    操作:
    (1)先建立数据访问层类库DAL,打开项目,在解决方案中右键——>添加——>新建项目——>选中类库——>改名DAL——>确定

    (2)在DAL中添加对Model的引用,点击DAL前▲——>右键点击引用——>添加引用——>项目——>选中Model——>确定

    (3)在DAL中添加对system.configuration的引用,点击DAL前▲——>右键点击引用——>添加引用——>程序集——>选中System.configuration——>确定

    (4)在建立的类文件中添加using Model;

    (5)建立数据访问类,右键DAL——>建立类——>建立实体类命名为:UserDB、

    UserDB类我只列举这几个方法:
    我们数据库就叫Aniki(因为这样很哲♂学)

            /// <summary>
            /// 填充表_注册新账号
            /// </summary>
            public void FillTable(UserInfo NewUser)
            {
                using (SQLiteConnection cnn = new SQLiteConnection(@"Data Source=D:Aniki.sqlite"))  //创建链接,链接到该数据库
                {
                    if (cnn.State != System.Data.ConnectionState.Open)                                  //判断数据库是否是打开,打开状态则不进行操作并关闭。
                    {
                        cnn.Open();                                                                     //打开数据库
                        using (SQLiteCommand cmd = new SQLiteCommand(cnn))                                    //创建对该数据库操作的命令
                        {
                            cmd.CommandText = "INSERT INTO UserList(Account, Password) VALUES('" + NewUser.UserAccount + "', '" + NewUser.UserPassword + "')";     //输入命令内容
                            cmd.ExecuteNonQuery();//执行cmd命令的sql语句
                        }
                    }
                    cnn.Close();
                }
            }
    
            /// <summary>
            /// 表内查找
            /// </summary>
            public DataTable SelectTable(UserInfo OldUser)
            {
                DataTable dt = new DataTable();
                using (SQLiteConnection cnn = new SQLiteConnection(@"Data Source=D:Aniki.sqlite"))
                {
                    if (cnn.State != System.Data.ConnectionState.Open)
                    {
                        cnn.Open();
                        
                        using (SQLiteCommand cmd = new SQLiteCommand(cnn))
                        {
                            cmd.CommandText = "SELECT * FROM UserList WHERE Account='" + OldUser.InputAccount + "'";
                            SQLiteDataAdapter adaper = new SQLiteDataAdapter(cmd);
                            adaper.Fill(dt);
                        }
                    }
                    cnn.Close();
                    return dt;
                }
            }
    

    3、业务逻辑层(BLL)对传送数据进行逻辑判断分折,并进行传送正确的值。

    (1)先建立业务逻辑层类库BLL,打开项目,在解决方案中右键——>添加——>新建项目——>选中类库——>改名BLL——>确定

    (2)在BLL中添加对Model、DAL的引用,右键BLL项目下的引用——>添加引用——>项目——>勾选Model和DAL——>确定

    (3)在建立的类文件中添加using Model;using DAL;

    (4)建立类,类名为:LoginManager

        public class LoginManager
        {
            //string NewAccount;
            //string NewPassword;
            //string ValidCode;
    
            /// <summary>
            /// 新用户_注册
            /// 验证密码和再次输入密码,两次密码正确则帐号和密码写入数据库
            /// </summary>
            /// <param name="NewUser">新用户</param>
            /// <returns></returns>
            public bool SignUpVerifyPassword(UserInfo NewUser)
            {
                UserDB Aniki = new UserDB();//创建数据库类以进行操作
                if (NewUser.UserPasswordConfirm == NewUser.UserPassword)//微软牛逼!
                {
                    Aniki.FillTable(NewUser);//写入数据库
                    return true;
                }
                else
                    return false;
            }
    
            /// <summary>
            /// 新用户注册查询
            ///查询是否以经被注册,所以作老用户属性来判断一下(用的代码部分与老用户登录类似,逻辑是看看这个帐号能不能返回密码)
            /// </summary>
            /// <param name="OldUser"></param>
            /// <returns></returns>
            public bool SignUpIsAccountExist(UserInfo OldUser)
            {
                UserDB Aniki = new UserDB();
                if (Aniki.SelectTable(OldUser).ToString() == "")
                {
                    return false;
                }
                else
                    return true;
            }
    

    上面为什么要把验证能不能注册这一个事情,分成两个函数呢?
    因为注册不成功的报错有两种:
    1,密码与重复输入密码不相符
    2,帐号已经注册
    因此我们要写成两个函数,对应两个massage.box()。

            /// <summary>
            /// 老用户_验证登录验证输入的密码
            /// </summary>
            /// <param name="OldUser"></param>
            /// <returns></returns>
            public bool LoginVerifyPassword(UserInfo OldUser)
            {
                UserDB Aniki = new UserDB();
                if (OldUser.InputPassword == (string)Aniki.SelectTable(OldUser).Rows[0][0])
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
                
            /// <summary>
            /// 老用户_修改密码
            /// </summary>
            /// <param name="OldUser"></param>
            /// <returns></returns>
            public bool UpdataPassword(UserInfo OldUser)
            {
                UserDB Aniki = new UserDB();
                if (OldUser.InputPassword == OldUser.PasswordInDB)
                {
                    Aniki.UpdataTable(OldUser);
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    

    4.表现层(UI)即用户界面层

    (1)先建立业务逻辑层类库BLL,打开项目,在解决方案中右键——>添加——>新建项目——>选中Winform——>改名UI——>确定

    (2)在BLL中添加对Model、BLL的引用,右键UI项目下的引用——>添加引用——>项目——>勾选Model和BLL——>确定

    (3)在建立的winform类文件中添加using Model;using BLL;

    Winform代码太难看了,这里只举个例子好了,这是点击LogIn按钮的内容,这里的逻辑比较有代表性。

    LogIn窗体内的Login按钮

    
    private void btnLogin_Click(object sender, EventArgs e)
            {
                UserInfo OldUser = new UserInfo();
                OldUser.InputAccount = tbUserAccount.Text;
                OldUser.InputPassword = tbUserPassword.Text;
                LoginManager BLL = new LoginManager();
                if (BLL.LoginVerifyPassword(OldUser))
                {
                    MessageBox.Show("登录成功!");
                    DialogResult = DialogResult.Cancel;//用于关闭本LogIn窗口
                    DialogResult = DialogResult.OK;//用于打开Main窗口
                    /*
                    原因:
                        Main窗口代码先运行,给LogIn窗口建立了个对象frmLogIn,frmLogIn的frmLogIn.ShowDialog()方法打开了LogIn窗口。
                        DialogResult是对话框的返回值,写在btnLogin_Click函数中,就是在btnLogin_Click函数中给这个DialogResult返回值赋值了OK(1)
                        回到Main窗体中判断LogIn中的DialogResult,如果是OK(1)就打开Main窗体,否则不打开。
                    */
                }
                else
                    MessageBox.Show("账号或密码错误!");
            }
    
    

    btnLogin_Click()这个方法是注册新用户的按钮,如果登录成功会跳转到Main窗体。这里引用了BLL层的BLL.LoginVerifyPassword()方法。
    之前以经展示过BLL.LoginVerifyPassword()这个方法,在BLL层中(因此建立了一个叫BLL的对象,代码是LoginManager BLL = new LoginManager();)

    BLL层的LoginVerifyPassword()方法

            public bool LoginVerifyPassword(UserInfo OldUser)
            {
                UserDB Aniki = new UserDB();
                if (OldUser.InputPassword == (string)Aniki.SelectTable(OldUser).Rows[0][0])
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
    
    

    这里的LoginVerifyPassword()方法有用到了DAL层的SelectTable()方法,SelectTable()方法是非常简单直接的一个方法,即返回你要查找的结果集(我这里的返回结果只有一个密码)

    DAL层的SelectTable()方法,这个方法是table类型的

            public DataTable SelectTable(UserInfo OldUser)
            {
                DataTable dt = new DataTable();
                using (SQLiteConnection cnn = new SQLiteConnection(@"Data Source=D:Aniki.sqlite"))
                {
                    if (cnn.State != System.Data.ConnectionState.Open)
                    {
                        cnn.Open();
                        
                        using (SQLiteCommand cmd = new SQLiteCommand(cnn))//建立一个SQLite命令对象cmd,构造函数需要cnn
                        {
                            cmd.CommandText = "SELECT * FROM UserList WHERE Account='" + OldUser.InputAccount + "'";//sql语句写入命令cmd
                            SQLiteDataAdapter adaper = new SQLiteDataAdapter(cmd);//DataAdapter是个数据转换器类,构造函数需要cmd
                            adaper.Fill(dt);
                            /*DataAdapter类里的Fill这个方法,可以填充DataSet或将DataSet表中的更改传送到相应的数据存储区,
                            从数据源增加或刷新行,并将这些行放到DataSet表中,Fill方法调用SelectCommand属性所指定的SELECT语句。*/
                        }
                    }
                    cnn.Close();
                    return dt;
                }
            }
    
    

    我们回到 BLL层的LoginVerifyPassword()方法

    if (OldUser.InputPassword == (string)Aniki.SelectTable(OldUser).Rows[0][0])
    

    这里DataTable SelectTable()是DataTable类型,返回一个DataTable类型的对象(原方法中对象是dt)
    这个对象的使用方式就是 dt.Rows[m][n],即像个二维数组一样返回想要位置的数值。Rows是按照行来算,Columns是按照列来算,此外还有很多方法。

    if (OldUser.InputPassword == (string)Aniki.SelectTable(OldUser).Rows[0][0])
    

    所以即表示返回第一个数据(我这里只有Password,所以就是第一个数据)
    强制类型转换未string,然后判断是不是与用户输入的InputPassword相符,相符则说明密码是符合的,即跳转Main窗体。

  • 相关阅读:
    BootStrap Table前台和后台分页对JSON格式的要求
    神奇的外部嵌套(使用ROW_NUMBER()查询带条件的时候提示列名无效)
    要想获取select的值,使用ng-modle,否则无法获取select 的值
    Angular使用操作事件指令ng-click传多个参数示例
    Jenins 邮件通知
    Jenkins 流水线(Pipeline)
    Jenkins Master-Slave 架构
    Jenins 参数化构建
    Jenkins 用户权限管理
    Jenkins 安装
  • 原文地址:https://www.cnblogs.com/maomaodesu/p/11418446.html
Copyright © 2020-2023  润新知