三层概述
数据访问层DAL(Data Access Layer)
(1)从数据源加载数据(Select)
(2)向数据源写入数据(Insert/Update)
(3)从数据源删除数据(Delete)
显示层UI
(1)向用户展现特定业务数据
(2)采集用户的输入信息的操作
UI设计的原则:用户至上,兼顾简洁
业务逻辑层BLL(Business Logic Layer)
(1)从DAL中获取数据,以供UI显示用
(2)从UI中获取用户指令和数据,执行业务逻辑
(3)从UI中获取用户和数据,通过DAL写入数据源
什么是七层?
七层就是在三层的基础上又增加了接口层、外观层、工厂层和实体层
1.实体层(Entity)存放全局的实体类,方便各个层之间的参数调用
2.数据访问层(DAL)该层所做事情是直接操作数据库,对数据的增删查改。不需要做什么逻辑判断,只是和数据库交互。
3.接口层(IDAL):接口层用来定义一个统一的接口,解除B层和D层的耦合。
4.工厂层(Factory):工厂来创建接口,返回接口,用到了抽象工厂+反射+配置文件,作用是灵活地实现数据库的连接,方便更换数据库
5.业务逻辑层(BLL):主要负责一些逻辑判断
6.外观层(Facade):用外观模式定义系统中每一层的入口,层与层之间不产生之间联系,而通过外观类建立联系,降低层之间的耦合度。
7.界面层(UI):主要职责是为用户提供信息并且接受用户输入的信息
包图
通过包图可以很清晰地看到各层之间的引用关系:
UI:Facade和Entity
Facade:BLL和Enetity
BLL:Factory、IDAL和Enetity
IDAL:Entity
Facotory:IDAL
DAL:IDAL和Entity
七层登录代码
UI界面层
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace UI
{
public partial class frmLogin : Form
{
public frmLogin()
{
InitializeComponent(); //每一个窗体生成的时候,针对当前窗体界面的定义方法
}
//登录按钮
private void btnLogin_Click(object sender, EventArgs e)
{
//判断卡号文本框是否输入为空
if (txtCardno.Text.Trim() == "")
{
MessageBox.Show("请输入卡号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtCardno.Focus();
return; //return语句用来结束该方法或函数
}
//判断密码文本框是否输入为空
if (txtPassword.Text.Trim() == "")
{
MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtPassword.Focus();
return;
}
//实例化一个外观
Facade.LoginFacade facade = new Facade.LoginFacade();
//实例化一个用户
Entity.UserInfo user = new Entity.UserInfo();
//接收信息
user.UserName = txtCardno.Text; //将文本框中的卡号赋值给user的UserName属性
user.Password = txtPassword.Text; //将文本框中的密码赋值给user的Password属性
//调用外观层的SelectUser()方法,返回一个bool值
Boolean flag = false;
Facade.LoginFacade flogin = new Facade.LoginFacade();
flag = flogin.SelectUser(user);
//判断是否登录成功
if (flag!=false)
{
//显示登陆成功,隐藏当前窗体
MessageBox.Show("登录成功");
this.Hide();
this.DialogResult = System.Windows.Forms.DialogResult.OK; //类似于对话框点击了确定按钮
Form a = new Form(); //实例化出一个新的窗体
a.Show();
}
else
{
MessageBox.Show("用户名或密码不正确");
txtCardno.Text = "";
txtPassword.Text = "";
txtCardno.Focus();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (MessageBox.Show("确认退出系统吗?","提示",MessageBoxButtons.OKCancel,MessageBoxIcon.Asterisk)==DialogResult.OK) //对话框点击了确定就强制退出
{
System.Environment.Exit(0); //强制退出
}
}
}
}
App.cnofig配置文件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<!--Connstr连接数据库,key,value 是一个键值对,key为键,value为值,根据key可以找到value值-->
<add key="connStr" value="server=DESKTOP-DHFP31D; database=wtt; uid=sa; password=123456" />
<add key="DB" value="DAL" />
</appSettings>
</configuration>
Entity实体层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Entity
{
public class UserInfo
{
//定义用户名字段属性
private string _username;
public string UserName
{
get { return _username; }
set { _username = value; }
}
//定义密码Password字段属性
private string _password;
public string Password
{
get { return _password; }
set { _password = value; }
}
}
}
Facade外观层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BLL;
namespace Facade
{
public class LoginFacade
{
public Boolean SelectUser(Entity.UserInfo user)
{
bool flag; //标记常量
LoginBLL userBLL = new LoginBLL(); //实例化一个LoginBLL类
flag = userBLL.UserBLL(user); //跳转到BLL层
return flag;
}
}
}
BLL业务逻辑层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Collections;
using Factory;
using IDAL;
using Entity;
namespace BLL
{
public class LoginBLL
{
//判断用户是否存在
public bool UserBLL(Entity.UserInfo user)
{
//实例化工厂
Factory.LoginFactory fact = new Factory.LoginFactory();
//调用工厂方法创建接口
IDAL.LoginIDAL idal = fact.CreateUser();
//接收D层的返回值
DataTable table = idal.SelectUser(user);
bool flag;
//返回数据表类型,如果行数=0,说明没有符合该账号密码的用户
if (table.Rows.Count==0)
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
}
}
Factory工厂层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Configuration;
using IDAL;
namespace Factory
{
public class LoginFactory
{
//获取配置文件
string strDB = System.Configuration.ConfigurationManager.AppSettings["DB"];
//应用反射来获取DAL层操作
public IDAL.LoginIDAL CreateUser()
{
string ClassName = strDB + "." + "LoginDAL"; //程序集+类名
return (IDAL.LoginIDAL)Assembly.Load(strDB).CreateInstance(ClassName); //反射+工厂
}
}
}
IDAL接口层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Xml;
namespace IDAL
{
//接口层
public interface LoginIDAL
{
//放置接口函数,判断要登录的用户名是否在数据表中存在
DataTable SelectUser(Entity.UserInfo user);
}
}
DAL数据访问层
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using IDAL;
using Entity;
namespace DAL
{
public class LoginDAL:LoginIDAL
{
public DataTable SelectUser(Entity.UserInfo user) //SelectUser方法是IDAL接口的方法
{
//实例化数据库操作类,进行数据查询,并获取返回值
SqlHelper sqlHelper = new SqlHelper();
SqlParameter[] sqlparams = { new SqlParameter("@cardno",user.UserName), new SqlParameter("@password",user.Password)};
string sqlquery = @"SELECT * FROM [card_info] WHERE cardno=@cardno AND password=@password"; //sql查询语句
DataTable table = sqlHelper.ExecuteQuery(sqlquery, sqlparams, CommandType.Text);
return table;
}
}
}
SqlHelper类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
namespace DAL
{
public class SqlHelper
{
//定义数据库连接操作,指定在数据上操作的类型,定义数据库读取操作
private SqlConnection conn = null; //SqlConnection中表示数据库一个打开的连接
private SqlCommand cmd = null; //SqlCommand表示SQL Server数据库执行一个Transact-SQL语句或者存储过程
private SqlDataReader sdr = null; //sqlDataReader提供一种从SQL Server数据库读取行的只进流的方式
//数据库连接
public SqlHelper()
{
string connStr = null;
connStr = ConfigurationManager.AppSettings["connStr"];
conn = new SqlConnection(connStr); //实例化一个连接
}
private SqlConnection GetConn()
{
if (conn.State==ConnectionState.Closed) //连接状态为关闭
{
conn.Open(); //打开连接
}
return conn;
}
//执行不带参数的数据库操作或存储过程
public int ExecuteNonQuery(string cmdText, CommandType ct)
{
int res;
cmd = new SqlCommand(cmdText, GetConn()); //打开连接
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
if (conn.State==ConnectionState.Open) //连接处于打开状态
{
conn.Close(); //关闭
}
return res;
}
//执行带参数的数据库操作或存储过程
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;
}
//执行不带参数的SQL查询语句或存储过程
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;
}
//执行带参数的SQL查询语句或存储过程
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;
}
}
}
Genuine knowledge comes from practice.
实践出真知,不要觉得它难,去做就好。