winform学习日志(十九)----------真正三层架构之登录
摘要:一:三层构架的基础知识在项目开发的过程中,有时把整个项目分为三层架构,其中包括:表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。三层的作用分别如下: 表示层:为用户提供交互操作界面,这一点不论是对于Web还是WinForm都是如此,就是用户界面操作。我们网站展示给用户看的界面。 业务逻辑层:负责关键业务的处理和数据的传递。复杂的逻辑判断和涉及到数据库的数据验证都需要在此做出处理。根据传入的值返回用户想得到的值,或者处理相关的逻辑。 数据访问层:见名知意
一:三层构架的基础知识
在项目开发的过程中,有时把整个项目分为三层架构,其中包括:表示层(UI)、业务逻辑层(BLL)和数据访
问层(DAL)。三层的作用分别如下:
表示层:
为用户提供交互操作界面,这一点不论是对于Web还是WinForm都是如此,就是用户界面操作
。我们网站展示给用户看的界面。
业务逻辑层:
负责关键业务的处理和数据的传递。复杂的逻辑判断和涉及到数据库的数据验证都需要在此
做出处理。根据传入的值返回用户想得到的值,或者处理相关的逻辑。
数据访问层:
见名知意,负责数据库数据的访问。主要为业务逻辑层提供数据,根据传入的值来操作数据
库,增、删、改或者其它。
以下我简单介绍下一个用户管理模块:
为了整个项目的开发方便,我们在项目中会建几个类库Common,BLL,DAL,Model。
为了命名清晰,我们可以这样命名这个三个工程(即在解决方案里添加的类库):
业务逻辑层(BusinessLogicLayer):BLL,命名空间默认设置为BLL
数据访问层(DataAccessLayer):DAL,命名空间默认设置为DAL
工具类:如:Common,命名空间默认设置为Common
另外我们为了数据传递的方便,通常再添加一个类库,这个类库是贯穿于整个三层架构中的。即实体类。
通常命名为Model,命名空间默认值设置为:Models。其中封装的每个类都对应一个实体,通常就是数据库
中的一个表。如数据库中的用户表(custom)封装为(custom),将表中的每个字段都封装成共有的属
性。
这样三层架构的搭建就基本完成了。这三层有着非常强的依赖关系:
表示层 ← 业务逻辑层 ← 数据访问层
他们之间的数据传递是双向的,并且通常借助实体类传递数据。
那么三层架构都有哪些优点呢:
1、易于项目的修改和维护。
在项目的开发过程中或者开发后的升级过程中,甚至在项目的移植过程中。
这种三层架构是非常方便的。比如项目从Web移植到Form,我们只需要将表示层重新做一遍就可以了。
其余两层不用改动,只需添加到现有项目就可以了。如果不采用这种架构,只是将代码写到表示层。那么
所有的编码几乎都要重新来了。
2、易于扩展。
在功能的扩展上同样如此,如有功能的添加只需把原有的类库添加方法就可了
3、易于代码的重用。
这一点就不用解释了。
4、易于分工协作开
还可以加个接口类库Iinterface, 加入设计模式,使你的代码灵活性更好,质量更高。
二:系统登录的例子
a,整体
b,OperationLogBLL.cs
class=”csharpcode”>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HRMSys.DAL;
namespace HRMSys.BLL
{
///
/// 插入操作记录
///
public class OperationLogBLL
{
OperationLogDAL dal = new OperationLogDAL();
public void InsertOperationLog(Guid id, string name, string ActionDesc)
{
dal.InsertLog(id, name, ActionDesc);
}
}
}
c,OperatorBLL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HRMSys.DAL;
using HRMSys.Model;
using Common;
namespace HRMSys.BLL.cs
{
public class OperatorBLL
{
OperatorDAL dal=new OperatorDAL();
///
/// 得到指定name的operator的数据
///
///
///
public Operator getOperatorByName(string name)
{
Operator op=new Operator();
op=dal.loginUser(name);
return op;
}
/// <summary>
/// 密码错误超过三次,锁定登录者
/// </summary>
/// <param name="op"></param>
public void updateOperator(Operator op)
{
dal.UpdateOperator(op);
}
/// <summary>
/// 登录
/// </summary>
/// <returns></returns>
public bool login(string name,int errorTime,string pwd,out string message,out Operator op)
{
bool r = false;
if (name.Length <= 0)
{
message = "请输入用户名";
op = null;
return r;
}
if (pwd.Length <= 0)
{
message = "请输入用户名";
op = null;
return r;
}
if (errorTime>=3)
{
message = "用户已被锁定";
op = null;
return r;
}
else
{
op = dal.loginUser(name);
if (op == null)
{
message = "用户名不存在";
}
else
{
pwd = CommonHelper.GetMD5(pwd + CommonHelper.getPasswordSalt());
if (op.Password != pwd)
{
message = "密码不正确";
op.IsLocked = true;
updateOperator(op);
return r;
}
else
{
if (op.IsLocked == true)
message = "用户被锁定";
else
{
r = true;
message = "登录成功";
}
}
}
return r;
}
}
}
}
d,OperationLogDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HRMSys.Model;
using System.Data;
using System.Data.SqlClient;
namespace HRMSys.DAL
{
public class OperationLogDAL
{
/// <summary>
/// 插入一条操作记录
/// </summary>
/// <param name="OperatorId"></param>
/// <param name="ActionDesc"></param>
public void InsertLog(Guid OperatorId, string loginUser, string ActionDesc)
{
sqlhelper.ExecuteNon(@"insert into T_OperationLog(Id,OperatorId,MakeDate,ActionDesc,LoginUser)
values(newid(),@OperatorId,getdate(),@ActionDesc,@LoginUser)", new SqlParameter("@ActionDesc", ActionDesc),
new SqlParameter("@OperatorId", OperatorId),
new SqlParameter("@LoginUser", loginUser));//这里是values,不是value
}
}
}
e,OperatorDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HRMSys.Model;
using System.Data.SqlClient;
using System.Data;
namespace HRMSys.DAL
{
public class OperatorDAL
{
/// <summary>
/// 将表的形式转换为vs的形式,给对象
/// </summary>
/// <param name="row"></param>
/// <returns></returns>
private Operator ToOperator(DataRow row)
{
Operator op = new Operator();
op.Id = (Guid)row["Id"];//不加就可以检查用户名是否重复了
op.UserName = (string)row["UserName"];
op.Password = (string)row["Password"];
op.IsLocked = (bool)row["IsLocked"];
op.IsDelete=(bool)row["IsDelete"];
op.RealName = (string)row["RealName"];
return op;
}
/// <summary>
///查询指定username的一条数据
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Operator loginUser(string name)
{
DataTable table = sqlhelper.datatable("select * from T_Operator where UserName=@UserName and IsDelete=0 and IsLocked=0",
new SqlParameter("@UserName", name));
if (table.Rows.Count <= 0)
return null;
else if (table.Rows.Count > 1)
throw new Exception("用户名重复");
else
{
DataRow row = table.Rows[0];
return ToOperator(row);
}
}
/// <summary>
/// 锁定管理员更新管理员表
/// </summary>
/// <param name="op"></param>
public void UpdateOperator(Operator op)
{
sqlhelper.ExecuteNon("update T_Operator set IsLocked=@IsLocked where Id=@Id",
new SqlParameter("@IsLocked", op.IsLocked),
new SqlParameter("@id",op.Id));
}
}
}
f,login.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using HRMSys.Model;
using HRMSys.BLL;
using HRMSys.BLL.cs;
namespace HYMSys.UI
{
public partial class login : Form
{
public login()
{
InitializeComponent();
}
int errorTime = 0;
string message;
Operator op;
OperationLogBLL logbll = new OperationLogBLL();
OperatorBLL bll = new OperatorBLL();
///
/// 登录,并保存登录操作记录
///
///
///
private void button1_Click(object sender, EventArgs e)
{
//返回是否登录成功的bool类型,并将提示信息和管理员对象返回
bool result= bll.login(tb_name.Text, errorTime, tb_pwd.Text, out message, out op);
if (result == false)
{
errorTime += 1;
MessageBox.Show(message);
return;
}
else
{
//插入一条操作记录
logbll.InsertOperationLog(op.Id, op.UserName, message);
MessageBox.Show(message);
}
}
/// <summary>
/// 取消
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
三:总结
这是一个非常简单但非常典型的一个三层架构的小例子,希望能给像我一样的初学者一些帮助。欢迎大家来积极的讨论。
winform学习日志(十九)----------真正三层架构之登录的更多相关文章
- python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法
python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...
- 学习笔记:CentOS7学习之十九:Linux网络管理技术
目录 学习笔记:CentOS7学习之十九:Linux网络管理技术 本文用于记录学习体会.心得,兼做笔记使用,方便以后复习总结.内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK ...
- 风炫安全web安全学习第二十九节课 CSRF防御措施
风炫安全web安全学习第二十九节课 CSRF防御措施 CSRF防御措施 增加token验证 对关键操作增加token验证,token值必须随机,每次都不一样 关于安全的会话管理(SESSION) 不要 ...
- 风炫安全WEB安全学习第十九节课 XSS的漏洞基础知识和原理讲解
风炫安全WEB安全学习第十九节课 XSS的漏洞基础知识和原理讲解 跨站脚本攻击(Cross-site scripting,通常简称为XSS) 反射型XSS原理与演示 交互的数据不会存储在数据库里,一次 ...
- (C/C++学习笔记) 十九. 模板
十九. 模板 ● 模板的基本概念 模板(template) 函数模板:可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计. 语法: template <<模 ...
- Salesforce LWC学习(三十九) lwc下quick action的recordId的问题和解决方案
本篇参考: https://developer.salesforce.com/docs/component-library/bundle/force:hasRecordId/documentation ...
- Java基础学习笔记十九 IO
File IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再 ...
- Java基础学习笔记十九 File
IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把这些数据 ...
- JAVA学习第十九课(java程序的异常处理 (二))
异常处理的捕捉形式: 这是能够对异常进行针对性处理的方式 六.try.catch的理解 详细格式: try { //须要被检測异常的代码 } catch(异常类 变量)//改变量用于接受发生异常的对象 ...
随机推荐
- 笔试面试题-寻找Coder
请设计一个高效算法,再给定的字符串数组中,找到包含"Coder"的字符串(不区分大小写),并将其作为一个新的数组返回.结果字符串的顺序按照"Coder"出现的次 ...
- vim 跳转命令
基本跳转: hjkl:左下上右 HML:当前屏幕顶.中.底部 web:下一单词词首.下一单词词尾.前一单词词首 gg:文件首 G:文件末尾 ngg/nG:第n行 ta:移动到所在行之后第一个字符a ...
- linux 安装mysql后修改密码出现问题
新安装的mysql 执行命令时候出现错误: 一 错误信息: ERROR 1045 (28000): Access denied for user 'mysql'@'localhost' (using ...
- C#基础(八)——C#数据类型的转换
C#数据类型的转换主要有以下几种方式: 1.强制转换 注意:char类型不能强制转换成int,如果使用强制转化,得到的是原整数的ASCII码值. 2.class.parse(string类型的变量), ...
- 一段画对角线的canvas代码,之前没有写过canvas代码,现在记录下来
<canvas id="other" style="width:320px;height:320px;"></canvas> var o ...
- cocos3.10 使用cocostudio 回调特性 c++版本说明
cocos3.10 使用cocostudio 回调特性 c++版本说明 好久没捣鼓cocos2dx了,又拿起来玩玩,看着版本一次次的升级,真的好快,今天用cocos3.10版本测试下时间特性功能,跟着 ...
- js判断选择时间不能小于当前时间的代码
判断选择时间不能小于当前时间的方法有很多,在本文为大家详细介绍下使用js是如何实现的,感兴趣的朋友可以尝试操作下 复制代码代码如下: var controldate; function checkD ...
- pdf转chm的实现方法
相比pdf, CHM电子书在Windows系统下不需要安装额外的浏览器即可进行阅读,其内容是基于浏览器的风格,更容易被用户所接受.而且, 具有更强大的功能配置,比如可提供强大的全文搜索.索引.书签等的 ...
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
Linux进程间通信IPC学习笔记之消息队列(SVR4)
- SQLite3中自增主键
SQLite清空表并将自增列归零 SQL标准中有TRUNCATE TABLE语句,用来清空表的所有内容. 但SQLite不支持这个语句.在SQLite中直接使用 DELETE FROM TableNa ...