Why should there be 7 floors?
Layer 7 passes through the calls between the layers, and then reduces the coupling between the three layers, so that our program can be expanded and modified more flexibly.
7-layer composition
For the 7th layer, it only has more Facade, IDAL, Factory and Entity layers than 3 layers.
1. Interface layer (UI): It is mainly used to collect the data entered by the user and then pass it to the appearance layer, and then pass it to the B layer for corresponding judgment.
2. Business logic layer (BLL): The B layer is mainly used for logical judgment, calling the method in the factory to create the corresponding interface.
3. Data Access Layer (DAL): implements the interface defined by the interface layer.
4. Facade: The purpose of using the appearance layer is to reduce the coupling between the U and B layers. The connection between the U and B layers only needs to go through the interface of the Facade layer, and the U layer does not need to know the B layer. What are the internal methods. The appearance layer receives the data from the U layer, and then calls the B layer method to verify the information.
5. Factory: Through the configuration file and abstract factory, we can change the code without changing the value in the configuration file to replace the database. The work that Factory needs to complete is to define an interface to call the interface layer to realize the data transfer between the BLL layer and the DAL layer.
6. Interface layer (IDAL): The interface layer is used to define a unified interface and decouple the B and D layers.
7. Entity: Same as the entity layer in the three layers, it is mainly used to transfer data among the layers.
7-tier reference relationship
UI layers | Facade layer Entity layer |
Facade层 | BLL layer Entity layer |
BLL | Entity layer Factory layer IDAL layer |
Factory layer | IDAL layers |
IDAL layers | Entity layer |
DAL layer | IDAL layer Entity layer |
Code
This is the naming of each layer of my program for reference only
Entity layer
namespace Login.Entity
{
public class UserInfo
{
//定义用户ID
private int userid;
public int UserID
{
get { return userid; }
set { userid = value; }
}
// 定义用户密码
private string userpwd;
public string UserPwd
{
get { return userpwd; }
set { userpwd = value; }
}
//定义用户等级
private string userlevel;
public string UserLevel
{
get { return userlevel; }
set { userlevel = value; }
}
//定义用户名字
private string username;
public string UserName
{
get { return username; }
set { username = value; }
}
}
}
IDAL layers
using System.Data;
namespace Login.IDAL
{
//D层接口层
public interface IUserInfoDAL
{
DataTable SelectUser(Login.Entity.UserInfo userinfo);
}
}
SqlHelp in the DAL layer
using System.Data.SqlClient;
using System.Data;
namespace LoginDAL
{
public class SqlHelper
{
private SqlConnection conn = null;
private SqlCommand cmd = null;
private SqlDataReader sdr = null;//这里是存放查询出来的数值的。
public SqlHelper()
{
string connStr = System.Configuration.ConfigurationManager.AppSettings["Connstr"];//从配置文件中读取连接的字符串
conn = new SqlConnection(connStr);
}
/// <summary>
/// 打开数据库连接
/// </summary>
/// <returns></returns>
private SqlConnection GetConn()
{
if (conn.State == System.Data.ConnectionState.Closed)
{
conn.Open();
}
return conn;
}
/// <summary>
/// 执行不带参数的增删改查SQL语句或存储过程
/// </summary>
/// <param name="cmdText">SQL语句或存储过程吗</param>
/// <param name="ct">执行的命令函数</param>
/// <returns>受影响的行数</returns>
public int ExecuteNonQuery(string cmdText, CommandType ct)
{
//受影响的行数
int res;
using (cmd = new SqlCommand(cmdText, GetConn()))
{
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
}
return res;
}
/// <summary>
/// 执行带参数的增删改SQL语句或存储过程
/// </summary>
/// <param name="cmdText">SQL语句或者存储过程吗</param>
/// <param name="paras">SQLCommand参数集合</param>
/// <param name="ct">执行的命令类型</param>
/// <returns></returns>
public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
int res;
using (cmd = new SqlCommand(cmdText, GetConn()))
{
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;
//commandBehavior.colseconnection 的作用是dataReader 关闭时其所对应的数据库连接也关闭
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;
}
}
}
SqlUserinfoDAL in the DAL layer
using Login.Entity;
using Login.IDAL;
namespace LoginDAL
{
public class SqlUserInfoDAL : IUserInfoDAL
{
public DataTable SelectUser(UserInfo userinfo)
{
SqlHelper sqlHelper = new SqlHelper();
string sql = "select * from User_Info where userID=@userId and pwd=@password";
SqlParameter[] paras = { new SqlParameter("@userID", userinfo.UserID), new SqlParameter("@password", userinfo.UserPwd) };
return sqlHelper.ExecuteQuery(sql, paras, CommandType.Text);
}
}
}
Factory layer
using System.Reflection;//这一步应用了抽象工厂中的反射
namespace Login.Factory
{
public class Factory
{
//读取配置文件中所用数据库名称
//1、ConfigurationManager--提供了对配置文件访问的一个类,这个类不能被继承
//2、AppSettings--类中点出来的方法,获取当前应用程序默认配置的 AppSettingsSection 数据
//3、["DB"]是我们在配置文件中自定义的,所对应的是value,配置文件中value是“DAL”
//4、Assembly是一个程序集
//这里的ConfigurationManager需要添加引用 system.Configuration 若是程序引用不成功就去添加引用中添加
string strDB =System.Configuration.ConfigurationManager.AppSettings["DB"];
//程序集名称
// private static string assemblyName = strDB + "DAL";
public Login.IDAL.IUserInfoDAL CreateUserInfoDal()
{
//要创建的类名
string className = strDB + "." + "SqlUserInfoDAL";
return (Login.IDAL.IUserInfoDAL)Assembly.Load(strDB).CreateInstance(className);
}
}
}
BLL layer
using System.Data;
namespace Login.BLL
{
public class LoginBLL
{
public bool SelectUser(Login.Entity.UserInfo userinfo)
{
Login.Factory.Factory fact = new Login.Factory.Factory();
Login.IDAL.IUserInfoDAL login = fact.CreateUserInfoDal();
//b层调D层
DataTable dt = login.SelectUser(userinfo);
bool flag;
//datatable 的总行数是0 说明没有这个用户
if (dt.Rows.Count == 0)
{
return flag = false;
}
else
{
return flag = true;
}
}
}
}
Facade层
namespace Facade
{
public class LoginFacade
{
public Boolean SelectUser(Login.Entity.UserInfo userInfo)
{
return new Login.BLL.LoginBLL().SelectUser(userInfo);
}
}
}
UI layers
namespace UI
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void BtnLogin_Click(object sender, EventArgs e)
{
//判断输入不能为空
if (TxtUserID.Text.Trim() == "")
{
MessageBox.Show("请填写账号", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (TxtPassword.Text.Trim() == "")
{
MessageBox.Show("请填写密码", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
//try
//{
//实例化一个用户
Login.Entity.UserInfo userInfo = new Login.Entity.UserInfo();
//实例化的用户接收文本框中输入的信息
userInfo.UserID = Convert.ToInt32(TxtUserID.Text.Trim());
userInfo.UserPwd = TxtPassword.Text;
//实例化外观层 将值返回给用户(userinfo)
Facade.LoginFacade loginFacade = new Facade.LoginFacade();
bool flag = false;
flag = loginFacade.SelectUser(userInfo);
//这里 flag已经是bool类型了。不需要在进行判断了
if (flag)
{
this.Hide();
MessageBox.Show("登录成功", "恭喜", MessageBoxButtons.OK);
}
else
{
MessageBox.Show("账号密码错误");
}
//}
//catch (Exception)
//{
// throw;
//}
}
}
}
UI layer configuration file
Configuration file is here
<?xml version="1.0" encoding="utf-8" ?>
<!--UTF是unico字符串类型,utf-8比较省空间-->
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<!--配置数据库,自己手动写-->
<appSettings>
<add key="DB" value="LoginDAL"/>
<add key="ConnStr" value="server=LM;Database=charge_sys1;User ID=sa;PassWord=123456"/>
</appSettings>
</configuration>
The key Value in the configuration file means a key-value pair. When we encounter the value corresponding to the key in the code, we can make the program return the value corresponding to the value through reflection.
Suggestion when writing 7-level login
The code sequence is best to be written in the following order, so that the upper layer can be used to call the code of the next layer.
Entity layer-IDAL layer-sqlhelper of DAL layer-sqlselectuser of DAL layer-Factory-BLL layer-Facade layer-UI layer