数往知来 三层架构 <十四>

三层架构_1

一、三层

就是把程序的各个部分都分离,尽量的底耦合,做到分工明确、责任明确

第一层:Dal   数据访问层

第二层 :Bll  业务逻辑判断层

第三层: UI   界面显示层

比如说数据访问的就专门负责执行对数据库的增删改查等操作,然后把查到的结果返回,其他的一概不管,

而逻辑判断层就专门负责对一些逻辑的判断,比如说用户登录给我一个用户名,然后我把用户名给数据访问层,让他到数据库里给我查有没有这个用户的信息,

然后把信息返回给我,然后我就进行盘断用户输入的用户名密码等是否正确,然后把登录的状态返回给UI层,

然后UI层就负责把用户名和密码传给逻辑判断层,让它进行判断用户名密码是否正确,然后告诉我登录的状态,ui层再给用户显示登录的状态,

这样做的好处:

--》代码的复用,就是说我要是用winfrom做一个程序然后用控制台再做一个程序,那么我逻辑判断层和数据访问层的代码值要写一次就可以了,以后直接拿来用就可以了

--》容易维护

三层做的登录小案例

================================数据访问层:对数据库进行操作=============================================

namespace _03三层实现登录

{
   /// <summary>
    /// 数据访问层
    /// </summary>
    public  class Person_Dal
    {
        /// <summary>
        /// 根据当前用户输入的用户名获取用户的详细信息
        /// </summary>
        /// <param name="uName"></param>
        /// <returns></returns>
        public Person  LoginUID(string uName)
        {
           //1、SQL语句
            string sql = "select * from Person where [email protected] and PIsDel=0";
            using (SqlDataReader read = SqlHelper.ExecuteReader(sql, System.Data.CommandType.Text, new SqlParameter("@name", uName)))
            {
               if (read.HasRows)

                {

                    if (read.Read())

                    {
                        //把读出来的数据存到一个类对象的属性里面,这个类是公用的,返回这个对象,在其他的类也就可以访问这些数据了
                        Person per = new Person();
                        per.PCID = read.GetInt32(1);
                        per.PCName = read.GetString(4);
                        per.PIsDel = read.GetBoolean (10);
                       per.PLoginName = read.GetString(3);
                        per.PPwd = read.GetString(6);
                        per.PType = read.GetInt32(2);
                        return per;
                    }
                    throw new Exception();
                }

                else

                {
                  return null;
                }

            }

        }

    }

}

                                                   -----    SqlHelper    ---------

/// <summary>

    /// 操作数据库的通用代码

    /// 抽象类,不能实例化

    /// </summary>

    public abstract  class SqlHelper

    {

        //APP配置文件的连接数据库的连接字符串

        private static readonly string connstr = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;

        /// <summary>

        /// 执行增删改操作,返回一个受影响行数

        /// </summary>

        /// <param name="cmdText">SQL语句</param>

        /// <param name="cmdType">执行类型(存储过程、SQL语句等)</param>

        /// <param name="par">以数组的形式提供执行命令的参数列表</param>

        /// <returns></returns>

        public static int ExecuteNonQuery(string cmdText, CommandType cmdType, params SqlParameter[] par)

        {

            using (SqlConnection con = new SqlConnection())

            {

                using (SqlCommand cmd=new SqlCommand ())

                {

                    PreparaCommand(con, cmd, cmdText, cmdType, par);

                    return cmd.ExecuteNonQuery();

                }  

            } 

        }

        /// <summary>

        /// 执行查询语句,返回第一行第一列

        /// </summary>

        /// <param name="cmdText"></param>

        /// <param name="cmdType"></param>

        /// <param name="par"></param>

        /// <returns></returns>

        public static object ExecuteScalar(string cmdText, CommandType cmdType, params SqlParameter[] par)

        {

            using (SqlConnection con = new SqlConnection())

            {

                using (SqlCommand cmd=new SqlCommand ())

                {

                    PreparaCommand(con, cmd, cmdText, cmdType, par);

                    return cmd.ExecuteScalar();

                }

            }

        }

        /// <summary>

        /// 返回一个SqlDataReader

        /// </summary>

        /// <param name="cmdText"></param>

        /// <param name="cmdType"></param>

        /// <param name="par"></param>

        /// <returns></returns>

        public static SqlDataReader ExecuteReader(string cmdText, CommandType cmdType, params SqlParameter[] par)

        {

            SqlConnection con = new SqlConnection();

            using (SqlCommand cmd=new SqlCommand ())

            {

                PreparaCommand(con, cmd, cmdText, cmdType, par);

                return cmd.ExecuteReader(System.Data .CommandBehavior .CloseConnection );

            }

        }

        /// <summary>

        /// 返回一个DataTable

        /// </summary>

        /// <param name="cmdText"></param>

        /// <param name="cmdType"></param>

        /// <param name="par"></param>

        /// <returns></returns>

        public static DataTable ExecuteDataTable(string cmdText, CommandType cmdType, params SqlParameter[] par)

        {

            using (SqlDataAdapter adapter=new SqlDataAdapter (cmdText ,connstr ))

            {

                DataTable dt = new DataTable();

                if (par!=null)

                {

                    adapter.SelectCommand.Parameters.AddRange(par);

                }

                adapter.SelectCommand.CommandType = cmdType;

                adapter.Fill(dt);

                return dt;

            }

        }

        /// <summary>

        /// 准备参数

        /// </summary>

        /// <param name="con">连接对象</param>

        /// <param name="cmd">执行命令</param>

        /// <param name="cmdText">SQL语句</param>

        /// <param name="cmdType">执行命令的类型(存储过程、SQL语句等)</param>

        /// <param name="par">以数组的形式提供执行命令的参数列表</param>

        private static void PreparaCommand(SqlConnection con, SqlCommand cmd, string cmdText, CommandType cmdType, params SqlParameter[] par)

        {

            con.ConnectionString = connstr;

            if (con.State ==  ConnectionState.Closed )

            {

                con.Open();

            }

            if (par!=null)

            {

                cmd.Parameters.AddRange(par);

            }

            cmd.Connection = con;

            cmd.CommandText = cmdText;

            cmd.CommandType = cmdType;

        }

    }

===============================================业务逻辑层:做一些逻辑判断========================================================

    /// <summary>

    /// 业务逻辑层

    /// </summary>

    public class Person_Bll

    {

        public Loginfet LoginSucceed(string uid, string pwd)

        {

            Person_Dal pd = new Person_Dal();

            pd.LoginUID(uid);

            //new一个Person对象,数据都存在person对象里

            Person per = new Person();

            string md5 = MD5Helper.MD5Change(pwd);

            if (per==null)

            {//如果是空的就是没有读取到数据

                return Loginfet.LoginError ;

            }

            else if (per.PPwd !=md5 )

            {//把密码转换成MD5值进行比较

                return Loginfet.PasswordError ;

            }

            else

            {

                return Loginfet.OK ;

            }

        }

    }

------------   把登录状态写成枚举返回    ----------------

   public enum Loginfet

    {

        OK,//登录成功

        LoginError,//登录失败

        PasswordError//用户名不存在

    }

  ============================================================UI层  :向用户显示界面  ==================================

        private void btnLogin_Click(object sender, EventArgs e)

        {

            Person_Bll pb = new Person_Bll();

            Loginfet lf= pb.LoginSucceed(txtUID.Text.Trim(), txtPWD.Text.Trim());

            if (lf== Loginfet.LoginError )

            {

                msgDiv1.MsgDivShow("用户名不存在",2);

                return;

            }

            else if (lf != Loginfet.PasswordError)

            {

                msgDiv1.MsgDivShow("密码错误", 1);

                return;

            }

            else

            {

                msgDiv1.MsgDivShow("登录成功");

            }

        }

------------------------------------------------一个Person类  共有的 用来存储读取出来的用户的详细信息==========================================

    public  class Person

    {

        //PID, PCID, PType, PLoginName, PCName, PPYName, PPwd, PGender, PEmail, PAreas, PIsDel, PAddTime

        public int PCID

        {

            get;

            set;

        }

        public int PType

        {

            get;

            set;

        }

        public string PLoginName

        {

            get;

            set;

        }

        public string PCName

        {

            get;set;

        }

        public string PPwd

        {

            get;

            set;

        }

        public bool PIsDel

        {

            get;

            set;

        }

}

MD5

一、MD5

MD5就是一整散列算法(Hash),任何长度的内容都可以计算出MD5散列值

--》MD5长度一般是32位的16进制数字符串(比如71f396e4134a1160d90bb1439876df31),MD5值的个数是有限的,但是源数据是无限的,

因此存在着不同的内容产生相同MD5值的概率。因此MD5算法不可逆,也就是只能得到内容对应的MD5值,无法由MD5值反推内容。

但是对不同的内容产生相同MD5值的概率非常非常非常低!同一个字符串计算出来的散列值是一样的

常用的地方

--》数据库存储的登录密码

数据库的保存的用户登录密码用明文来存储是不安全的,这样数据库管理员、黑客就很容易看到用户的密码了

Password字段保存用户输入密码的MD5值,这样系统管理员、黑客也不知道用户的密码是什么,也就避免了用户的其他系统密码被利用的问题判断密码正确性的方法:计算用户输入的密码的MD5值,与数据库存储的MD5值进行比较,如果相等则认为密码正确。

为什么很多网站只有密码重置,没有找回原密码功能?。

--》因为MD5具有不可逆性,数据库里存的 是MD5值,它也不知道你的密码是多少

--》MD5可以计算一个字符串的散列值,也可以计算一个文件的散列值

/// <summary>

        /// 把字符串转换成MD5的方法

        /// </summary>

        /// <param name="str">要转换的字符串</param>

        /// <returns></returns>

        public string MD5Change(string str)

        {

            //需要一个MD5对象,MD5是密封类不能直接new

            MD5 md5 = MD5.Create();

            //把要转换的字符串转换成字节流byte[]

            //把字符串转成byte数组的时候,使用不同编码转换结果有时会不同(一般指双字节字符。)

            byte[] md5Byte = System.Text.Encoding.Default.GetBytes(str);

            //根据这个字符串的字节数组计算出这个字符串的MD5值,返回的是一个byte数组

            byte[] resMD5 = md5.ComputeHash(md5Byte );

            //用完要清空

            md5.Clear();

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i <resMD5 . Length; i++)

            {   //直接tostring()返回的是十进制的,我们要的是十六进制

                sb.Append(resMD5 [i].ToString ("x2"));

            }

            //把sb  tostring()返回

            return sb.ToString();

        }

        /// <summary>

        /// 把文件转换成MD5

        /// </summary>

        /// <param name="path"></param>

        /// <returns></returns>

        public static string MD5ChangeFile(string path)

        {

            //把文件读进来

            using (FileStream read=new FileStream (path,FileMode.Open  ))

            {

                //创建一个MD5对象

                MD5 md5 = MD5.Create();

                //转换

                byte[] MD5Byte= md5.ComputeHash(read);

                md5.Clear();

                StringBuilder sb = new StringBuilder();

                for (int i = 0; i <MD5Byte . Length; i++)

                {

                    sb.Append(MD5Byte[i].ToString ("x2") );

                }

                return sb.ToString();

            }

        }

三层的作用

复习委托:把老师的MsgDiv插件看一看,里面是委托实现的

一、三层  为了实现程序模块化,把一些单独的工能单独的封装起来实现代码的分离,便于日后的维护,和代码的重用

  --》表示层(UI)

作用:和用户交互,用户可以通过我们的程序看到数据库里的数据,展示数据给用户看,用户还可以提交数据

  --》业务逻辑层(BLL)

作用:提供具体的业务逻辑,隔离UI和Dal

  --》数据访问层(Dal)

作用:操作数据库

三个层之间的应用关系

数据访问层引用Model层

业务逻辑层应用数据访问层和Model层

表现层引用Model层和业务逻辑层

  -->实体(Model)

作用:在三层中传递数据这个不属于三层里的一个层,是用来存放类和类之间的公共数据

时间: 2024-11-04 20:31:31

数往知来 三层架构 <十四>的相关文章

如鹏网.Net三层架构 第四章代码生成器

介绍商业及代码生成器,如何自己手写代码生成器 SELECT * from information_schema.`TABLES` WHERE TABLE_TYPE='base Table' and `ENGINE`='InnoDb' and TABLE_SCHEMA='rpcaterdb' SELECT * from information_schema.`COLUMNS` where TABLE_NAME='t_orders' 1. 完全手写采用三层架构(不借助于代码生成器)编写一个学生的增删

PowerBuilder编程新思维3:适配(三层架构与GraphQL)

PowerBuilder编程新思维3:适配(三层架构与GraphQL) PB在富客户端时代,是一线开发工具.随着网络发展,主流架构演进到三层架构的时代,PB拿不出有力的三层架构,已经明显力不从心,市场份额也江河日下.今天我们来细数一下PB的三层架构方式及其改进方法. PB三层架构方式一:EAServer 这是PB官方首推的三层架构,但是用三句可以总结,无感的体验,无奈的价格,无语的速度. 事实上除了EAServer这个选择,可以自己开发服务端,比如topwiz公司的PBNIServ 使用BPNI

淘宝从几百到千万级并发的十四次架构演进之路!

1.概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知,文章最后汇总了一些架构设计的原则. 2.基本概念 在介绍架构之前,为了避免部分读者对架构设计中的一些概念不了解,下面对几个最基础的概念进行介绍: 分布式系统中的多个模块在不同服务器上部署,即可称为分布式系统,如Tomcat和数据库分别部署在不同的服务器上,或两个相同功能的Tomcat分别部署在不同服务器上 高可用系统中部分节点失效时,

C#三十五 三层架构企业应用

1.1          三层架构简介 假如你在经营一个大饭店,大体上你会请三方面的人,一方面是负责饭店服务的服务员,一方面是负责烹饪.做饭的厨师,一方面是负责饭店蔬菜.肉类.调料等的采购员. 如果你这样做了,那么饭店管理起来,就好比较好管理(简单来说).比如任何一方面的员工出现请假或离职的情况,可以找其他的服务员.厨师或采购员代替. 在企业中这种职责分离.业务独立的部门划分方法对于管理企业有很大的好处,同样在程序中也需采用"职责分离.业务独立的"的原则划分模块,更好的实现"

C#三十六 三层架构的实现

2.1 使用DataSet构建三层结构 开发三层结构应用系统时,在表示层.业务逻辑层.数据访问层各层中如何使用DataSet呢?DataSet在三层结构中的层次如下图所示: 从图中可以看出,在三层结构中,DataSet的构建和解析工作主要在表示层.数据访问层完成,业务逻辑层主要对DataSet中的数据进行加工.处理和传递.简单地说,DataSet是整个三层结构中数据传递的介质. 2.2 三层结构中DataSet的使用 2.2.1 在表示层中使用DataSet 在表示层中使用DataSet需要做两

对硅谷和硅谷科技公司的十四问,全程干货

引用: http://www.36kr.com/p/219345.html 从硅谷公司哪家强,到人人在议的泡沫问题,大数据和人工智能如何结合?2015年的科技前瞻是怎样一副图景?来自硅谷的Coursera软件工程师董飞将其近日在斯坦福公开讲座上的干货和各种场合的问答整理出来和大家分享.文中有他的一手从业经验,也有其对亲身就职或深度研究过的一些公司具体分析,如Hadoop.Amazon.LinkedIn等.董飞的知乎页面在这里,邮箱是[email protected]. 1.目前硅谷最火最有名的高

第十四章——循环神经网络(Recurrent Neural Networks)(第二部分)

本章共两部分,这是第二部分: 第十四章--循环神经网络(Recurrent Neural Networks)(第一部分) 第十四章--循环神经网络(Recurrent Neural Networks)(第二部分) 14.4 深度RNN 堆叠多层cell是很常见的,如图14-12所示,这就是一个深度RNN. 图14-12 深度RNN(左),随时间展开(右) 在TensorFlow中实现深度RNN,需要创建多个cell并将它们堆叠到一个MultiRNNCell中.下面的代码创建了三个完全相同的cel

三层架构1

一.三层框架 表现层:也叫视图层,用html.css.js.jquery 业务逻辑层:也叫控制层,包含业务逻辑的实现部分 数据管理层:与数据库直接交互的部分 二.组建三层框架(现有实例) 1.数据管理层 A.引入Model类 创建项目之后在项目的同级目录上建立Model的目录,相应的在保存项目的硬盘上也建立Model的目录.然后把Model.Base复制到硬盘上也建立的Model目录下,并在项目的Model下引入硬盘Model.Base线面现有的Model.Base.csproj模块. B.在项

[转]从三层架构到MVC,MVP

本来是不想跳出来充大头蒜的,但最近发现园子里关于MVC的文章和讨论之风越刮越烈,其中有些朋友的观点并不是我所欣赏和推荐的,同时最近也在忙着给公司里的同事做MVC方面的“扫盲工作”.所以就搜集了一些大家接触MVC的过程中经常出现的问题做了一下解释说明,希望能与大家多多交流,呵呵. 当然这种架构模式本身的一些问题也会在接下来的内容就加以介绍,另外就是如果大家有什么不同观点的话,欢迎拍砖(只要不打脸就行,呵呵). 一.  MVC是谁提出的         模型-视图-控制器(MVC)是Xerox PA