版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37508531/article/details/81710480
前言
在三层之后,我们接触到了七层登录,在七层中,我们接触到了外观模式,工厂模式和接口隔离原则,相应的也就比三层多了三个层(三层本身具有一个实体层):Facade、Factory、IDAL,那么现在我们就一起来了解一下七层登录吧!
过程
1.新建层
打开VS→新建项目→类库→删除默认类→建立自己的类,这就是一个层的建立过程,建立其他层的话可以直接右击解决方案→添加类库→删除默认类→建立自己的类即可。按照这样依次添加Entity,DAL,BLL,Facade,Factory,IDAL,UI,需注意UI层是一个窗体程序,并且把它设为启动项目。
小知识:新建类库时要新建.NET Framework类型的类库,因为这个是用于创建c#类库的项目。
2.添加引用
右击引用→添加引用即可。
层名 | 引用关系 |
UI层 | Facade层、Entity层 |
Facade层 | BLL层、Entity层 |
BLL层 | Factory层、Entity层、IDAL层 |
Factory层 | IDAL层 |
IDAL层 | Entity层 |
DAL层 | IDAL层、Entity层 |
Entity层 | 无 |
3.敲代码
敲代码的逻辑顺序为:Entity层→IDAL层→D层→Factory层→BLL层→Facade层→UI层。这样敲的好处是你用到的方法都会有,不会报红线。
首先是Entity层:就是登录用到的一些字段 |
public class UserInfo
{
//定义 用户ID 字段
private string userid;
public string UserID
{
get { return userid; }
set { userid = value; }
}
//定义 密码 字段
private string password;
public string Password
{
get { return password; }
set { password = value; }
}
}
这些只是登录时候用到的一些字段,之后实现其他功能的时候在添加即可。
IDAL接口层:添加与D层的接口 |
using System.Data;
namespace IDAL
{
public interface LoginIDAL
{
DataTable selectUser(Entity.UserInfo UserInfo);
}
}
D层:类DAL:实现IDAL层并且与数据库进行交互 |
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
public class LoginDAL:IDAL.LoginIDAL
{
public DataTable selectUser(Entity.UserInfo UserInfo) //selectUser该方法即是IDAL接口的方法
{
SQLHelper SQLHelper = new SQLHelper(); //实例化 跳转到SQLHelper层
//声明一个SQL参数的数组 params可变数组
SqlParameter[] sqlParams = { new SqlParameter("@txtUserID", UserInfo.UserID), new SqlParameter("@txtPWD", UserInfo.Password) }; //用户名和密码
string sql = @"SELECT * FROM User_Info WHERE UserID=@txtUserID and PWD=@txtPWD and state='True' "; //查 的语句 用户名 和 密码 相等 并且 状态为 True
DataTable table = SQLHelper.ExecuteQuery(sql, sqlParams,CommandType.Text);
return table;
}
}
}
D层:类SQLHelper:实现类DAL的一些方法 |
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
public class SQLHelper
{
#region 构造函数
private SqlConnection conn = null; //SqlConnection 打开连接
private SqlCommand cmd = null; //SqlCommand对象允许你指定在数据库上执行的操作的类型。比如,你能够对数据库中的行数据执行select,insert,modify以及delete命令。
//SqlCommand对象能被用来支持断开连接数据管理的情况,可以只单独使用SqlCommand对象。也可以与SqlDataAdapter一起实现断开数据连接,实现操作数据库的应用程序
private SqlDataReader sdr = null; //读取只进的行流的方式
public SQLHelper()
{
string connStr = ConfigurationManager.AppSettings["connStr"]; //ConnStr 是配置文件里连接数据库的关键字,引用这一句可以连接数据库
conn = new SqlConnection(connStr); //实例化一个连接
}
#endregion
#region SQL连接打开
private SqlConnection GetConn()
{
if (conn.State == ConnectionState.Closed) //如果连接状态为关闭
{
conn.Open(); //则打开
}
return conn;
}
#endregion
#region 非存储过程
/// <summary>
/// 执行不带参数的的 增删改 SQL语句或者存储过程
/// </summary>
/// <param name="cmdText">增删改SQL</param>
/// <param name="ct">命令类型</param>
/// <returns>返回受影响的行数</returns>
public int ExecuteNonQuery(string cmdText, CommandType ct)
//增删改 SQL 命令类型
{
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())) //使用using,可以自动关闭数据库
{
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;
}
#endregion
}
}
SQLHelper的代码很多,但是在进行其他功能的时候不用再对其进行更改。
Factory层:接收配置文件的数据并且连接D层 |
using System.Reflection;
using System.Configuration;
namespace Factory
{
public class LoginFactory
{
string StrDB = ConfigurationManager.AppSettings["DB"]; //接收来自配置文件的数据
public IDAL.LoginIDAL CreateUser()
{
string ClassName = StrDB + "." + "LoginDAL"; //这里的LoginDAL是D层的类名
return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName); //反射加工厂的应用
}
}
}
BLL层:业务逻辑的判断 |
using System.Data;
namespace BLL
{
public class LoginBLL
{
public bool UserBLL(Entity.UserInfo UserInfo)
{
Factory.LoginFactory fact = new Factory.LoginFactory(); //实例化工厂 跳转到Factory层 接收配置文件的数据,接收完成之后再回来
IDAL.LoginIDAL idal = fact.CreateUser(); //调用工厂方法创建接口 跳转Factory 使用CreateUser的方法
DataTable table = idal.selectUser(UserInfo); //接收D层的返回值 跳转到DAL层
bool flag;
if (table.Rows.Count == 0) //返回DataTable类型,如果他的行数等于0,说明没有符合该账号密码的用户
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
}
}
Facade层:接触UI层和B层的耦合 |
using System;
using System.Data;
namespace Facade
{
public class LoginFacade
{
public Boolean SelectUser(Entity.UserInfo user)
{
bool flag; //标记常量
BLL.LoginBLL userBLL = new BLL.LoginBLL(); //实例化
flag = userBLL.UserBLL(user); //跳转到BLL层
return flag;
}
}
}
UI层:用于显示 |
using System;
using System.Data;
using System.Windows.Forms;
namespace UI
{
public partial class frmLogin : Form
{
public frmLogin()
{
InitializeComponent(); //跳转到Designer的InitializeComponent方法
} //InitializeComponent方法走完之后跳到这,跳回Programs
private void BtnOK_Click(object sender, EventArgs e)
{
//判断输入不能为空
if (txtUserID.Text.Trim() == "")
{
MessageBox.Show("亲,请输入用户名哦", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (txtPWD.Text == "")
{
MessageBox.Show("亲,请输入密码哦", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
Entity.UserInfo user = new Entity.UserInfo(); //实例化user
user.UserID = txtUserID.Text.Trim(); //把在文本框中输入的东西转化为int32类型赋值给UserID
user.Password = txtPWD.Text; //密码赋值给Password
Boolean flag = false; //一个布尔值,在程序中控制是否允许移动: 当鼠标左键被按下时,flag=TRUE,此时允许MouseMove事件激发,同时设定允许窗体位置随着
//鼠标移动而移动; 当松开鼠标左键,那么即便鼠标移动,窗体不能随其移动而移动,所以flag=false
Facade.LoginFacade FLogin = new Facade.LoginFacade(); //实例化外观 FLogin
flag = FLogin.SelectUser(user); //调用外观的方法,返回给user 跳到Facade层
if (flag != false)
{
this.Hide(); //隐藏当前窗体
this.DialogResult = System.Windows.Forms.DialogResult.OK;
MessageBox.Show("登陆成功","提示");
else
{
MessageBox.Show("用户名或者密码错误");
txtUserID.Text = "";
txtPWD.Text = "";
txtUserID.Focus();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
System.Environment.Exit(0); //最彻底的退出方式,强制退出
//this.Close(); //只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出;
//Application.Exit(); //强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出;
//Application.ExitThread(); //强制中止调用线程上的所有消息,同样面临其它线程无法正确退出的问题;
}
}
}
配置文件里添加的代码 |
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<appSettings>
<add key="ConnStr" value="server=(local);database=Computer;uid=sa;pwd=123456"/>
<add key="DB" value="DAL"/>
<!--ConnStr 为 连接数据库 key为键值,引用字符DB,value代表引用的真正的内容-->
</appSettings>
</configuration>
4.逻辑顺序
启动后,进入UI层→Facade层→BLL层→Factory层→BLL层→DAL层→SQLHelper层→DAL层→BLL层→Facade层→UI层
总结
这就是使用七层登录的过程,有什么问题或者建议希望大家提出来,同时也希望这篇博客可以给初重构的大家一些帮助,成功登录之后一定要多调试几遍,看看代码的执行过程。