数往知来 三层架构 <十四>
三层架构_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 PLoginName=@name 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();
per.PCName = read.GetString();
per.PIsDel = read.GetBoolean ();
per.PLoginName = read.GetString();
per.PPwd = read.GetString();
per.PType = read.GetInt32();
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();
return;
}
else if (lf != Loginfet.PasswordError)
{
msgDiv1.MsgDivShow();
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();
; 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();
; i <MD5Byte . Length; i++)
{
sb.Append(MD5Byte[i].ToString ("x2") );
}
return sb.ToString();
}
}
三层的作用
复习委托:把老师的MsgDiv插件看一看,里面是委托实现的
一、三层 为了实现程序模块化,把一些单独的工能单独的封装起来实现代码的分离,便于日后的维护,和代码的重用
--》表示层(UI)
作用:和用户交互,用户可以通过我们的程序看到数据库里的数据,展示数据给用户看,用户还可以提交数据
--》业务逻辑层(BLL)
作用:提供具体的业务逻辑,隔离UI和Dal
--》数据访问层(Dal)
作用:操作数据库
三个层之间的应用关系
数据访问层引用Model层
业务逻辑层应用数据访问层和Model层
表现层引用Model层和业务逻辑层
-->实体(Model)
作用:在三层中传递数据这个不属于三层里的一个层,是用来存放类和类之间的公共数据
数往知来 三层架构 <十四>的更多相关文章
- 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)
阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ...
- PowerBuilder编程新思维3:适配(三层架构与GraphQL)
PowerBuilder编程新思维3:适配(三层架构与GraphQL) PB在富客户端时代,是一线开发工具.随着网络发展,主流架构演进到三层架构的时代,PB拿不出有力的三层架构,已经明显力不从心,市场 ...
- Alink漫谈(十四) :多层感知机 之 总体架构
Alink漫谈(十四) :多层感知机 之 总体架构 目录 Alink漫谈(十四) :多层感知机 之 总体架构 0x00 摘要 0x01 背景概念 1.1 前馈神经网络 1.2 反向传播 1.3 代价函 ...
- winform学习日志(十九)----------真正三层架构之登录
摘要:一:三层构架的基础知识在项目开发的过程中,有时把整个项目分为三层架构,其中包括:表示层(UI).业务逻辑层(BLL)和数据访问层(DAL).三层的作用分别如下: 表示层:为用户提供交互操作界面, ...
- jquery 调用wcf 的SOA架构,将三层架构运用到SOA的架构中来(第四天)
经过前面3天的学习,我想大家应该对SOA的架构有了初步的了解,其实 SOA与三层架构并不冲突,而是三层架构的升级版. 来看下传统的三层架构! 一共可以分为4个层: 模型层(可有可无),客户端,服务端, ...
- C# Dapper基本三层架构使用 (四、Web UI层)
三层架构的好处,一套代码无论WinForm还是Web都可以通用,只写前台逻辑就可以了,现在展示Web调用三层的示例 首先在项目中创建一个Web MVC5项目,目前项目目录如下 在Web项目Web.co ...
- 第十四章——循环神经网络(Recurrent Neural Networks)(第二部分)
本章共两部分,这是第二部分: 第十四章--循环神经网络(Recurrent Neural Networks)(第一部分) 第十四章--循环神经网络(Recurrent Neural Networks) ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- asp.net三层架构 及其中使用泛型获取实体数据介绍
asp.net中使用泛型获取实体数据可以发挥更高的效率,代码简洁方便,本例采用三层架构.首先在model层中定义StuInfo实体,然后在 DAL层的SQLHelper数据操作类中定义list< ...
随机推荐
- struts2与struts1整合,Unable to load configuration. - interceptor-ref ... struts.xml
struts.xml中为了与struts1的MVC模式整合,需要类似如下的拦截器的引用 <interceptor-stack name="integration"> & ...
- GitHub的使用 —— 如何删除Repository
如果要在GitHub上删除一个已经存在的Repository,该怎么办呢 ? 1.首先,点击这个资源(Repository),进入.会看到如下页面: 2.点击 Admin .在 Admin 页面的最下 ...
- EntityFramework:支持同一事务提交的批量删除数据实现思路
一切从一段代码说起... 下面一段代码是最近我在对一EF项目进行重构时发现的. protected override void DoRemove(T entity) { this.dbContext. ...
- 使用Aspose.Cells组件生成Excel文件
生成带表头的Excel文件,格式如下显示. 当然更复杂的一些也可以通过 合并单元格的方法 public void Merge(int firstRow, int firstColumn, int to ...
- POJ 2236 (简单并查集) Wireless Network
题意: 有n个电脑坏掉了,分别给出他们的坐标 有两种操作,可以O x表示修好第x台电脑,可以 S x y表示x y是否连通 两台电脑的距离不超过d便可连通,两台电脑是连通的可以直接连通也可以间接通过第 ...
- 【同行说技术】iOS程序员从小白到大神必读资料汇总
在文章<iOS程序员从小白到大神必读资料汇总(一)>里面介绍了很多iOS入门学习的资料,今天小编就发几篇技术进阶的文章,快来看看吧! 一.iOS后台模式开发指南 这个教程会教你在什么时候怎 ...
- 《C#高级编程》之泛型--1创建泛型类
.NET自从2.0版本开始就支持泛型. 非泛型链表 闲话休提,马上来看下非泛型的简化链表类,它可以包含任意类型的对象. LinkedListNode.cs中: 在链表中,一个元素引用另一个元素,所以必 ...
- Linux Shell编程(4): 逻辑运算符、逻辑表达式详解
shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决我们很多复杂的判断,达到事半功倍效果. 一.逻辑运算符 逻辑卷标 表示意思 1. 关于档案与目录的侦测逻辑卷标! -f 常用!侦测 ...
- NTP时间服务器配置与解析
NTP时间服务器配置与解析 Edit By ZhenXing_Yu 目 录 编译安装ntp server 2 修改ntp.conf配置文件 2 配置时间同步客户机 2 在服务端验证: 3 在客户端进行 ...
- php 计算本月第一天 本月最后一天 下个月第一天
本文转载自 http://jin541223.blog.163.com/blog/static/1637398052011111233018533/ //本周第一天(星期日为一周开始) echo ...