C#之七层登录
在三层基础之上,延伸出了七层,把UI层,BLL层和DAL之间的耦合度(联系紧密程度)又进一步的降低,先来看一下简略包图,看看它们之间的关系:
从这个包图上可以看见,增加了外观层,接口层,抽象工厂层,实体层,实体层可以看做是三层里的Model层,从结果上来看,它们的功能是相似的。
外观层主要是把UI层和BLL层分离;抽象工厂加反射主要是为了更换数据库的方便性,同时把DAL层中的类转换成IDAL层中的接口,从而使BLL层实现通过调用IDAL从而调用DAL层;接口层主要是为了把BLL层和DAL层分离。
七层的功能
1、界面层(UI):主要用于收集用户输入的数据然后传给外观层,再由外观层传给B层进行相应的判断。
2、业务逻辑层(BLL):B层主要是进行逻辑判断的,调用工厂中的方法创建相应的接口。
3、数据访问层(DAL):实现接口层定义的接口。
4、外观层(Facade):运用外观层的目的是降低U层和B层之间的耦合,U层和B层之间的联系只需要通过Facade层的接口就行了,U层无需知道B层内部有哪些方法。外观层接收U层传来的数据,然后调用B层的方法对信息进行验证。
5、工厂层(Factory):通过配置文件和抽象工厂我们可以实现不更改代码,换一下配置文件中的value值就可以更换数据库了。Factory还需要完成的工作就是定义一个接口调用接口层,实现BLL层和DAL层之间的数据传递。
6、接口层(IDAL):接口层是用于定义一个统一的接口,解除B层和D层的耦合。
7、实体层(Entity):和三层中的实体层一样,主要是用来在各层中传递数据。
上面的包图把引用关系阐述的已经很明白,那么开始实践,同时与三层相同的提醒,注意命名是否一致。
APP配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<appSettings>
<add key ="ConnStr" value="server=.; database=Login;User ID = sa ; Password=123456"/>
<!--<add key ="DB" value="DAL" />-->
<!--SqlServer是D层类的前缀,用来区别使用的是什么类型的数据库-->
<add key="DB" value="Login.DAL"/>
</appSettings>
</configuration>
实体层Entity:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Login.Entity
{
public class UserInfo
{
private string _userName;
private string _passWord;
public string UserName
{
get { return _userName; }
set { _userName = value; }
}
public string Password
{
get { return _passWord; }
set { _passWord = value; }
}
}
}
数据访问层DAL:
LoginDAL类
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 DAL;
namespace Login.DAL
{
public class LoginDAL:Login.IDAL.LoginIDAL
{
public DataTable SelectUser(Entity.UserInfo userInfo)
{
CommandType Text = 0;
SqlHelper sqlhelper = new SqlHelper();
SqlParameter[] sqlParams = { new SqlParameter("@UserName", userInfo.UserName), new SqlParameter("@PassWord", userInfo.Password) };
string sql = @"SELECT ID,UserName,Password,Email FROM USERS WHERE aaa@qq.com AND aaa@qq.com";
DataTable table = sqlhelper.ExecuteQuery(sql, sqlParams,Text);
return table;
}
}
}
SQLHelper类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
namespace DAL
{
//数据访问层,数据操作类
public class SqlHelper
{
//定义数据库连接操作,指定在数据库上操作的类型
private SqlConnection conn = null;
private SqlCommand cmd = null;
private SqlDataReader sdr = null;
//数据库连接
public SqlHelper()
{
string connStr = ConfigurationManager.AppSettings["connStr"];
conn = new SqlConnection(connStr);
}
private SqlConnection GetConn()
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
return conn;
}
///<summary>
///执行不带参数的数据库操作或者存储过程
/// 增删改查操作
/// 返回受影响的行数
///</summary>
public int ExecuteNonQuery(string cmdText, CommandType ct)
{
int res;
cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
if (conn.State == System.Data.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(System.Data.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;
}
}
}
业务逻辑层BLL:
LoginBLL类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data;
namespace Login.BLL
{
public class LoginBLL
{
public bool UserBLL(Entity.UserInfo userInfo)
{
Login.Factory.LoginFactory fact = new Login.Factory.LoginFactory();
IDAL.LoginIDAL idal = fact.CreateUser();//调用工厂方法创建接口
DataTable table = idal.SelectUser(userInfo);//接收D层返回值
Boolean flag;
if (table.Rows.Count == 0)
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
}
}
外观层Facade:
LoginFacade类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Login.Facade
{
public class LoginFacade
{
public Boolean SelectUser(Entity.UserInfo userInfo)
{
bool flag;
Login.BLL.LoginBLL userBLL = new Login.BLL.LoginBLL();
flag = userBLL.UserBLL(userInfo);
return flag;
}
}
}
抽象工厂层Factory:
LoginFactory类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;//对配置文件的引用
using System.Reflection;//对反射的引用
using System.IO;
namespace Login.Factory
{
public class LoginFactory
{
//数据程序集名称,命名空间(DAL)
string AssemblyName = "Login.DAL";
//接收来自配置文件的数据,这里是接收D层类名的前缀,用来区别数据库类型
string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"];
public IDAL.LoginIDAL CreateUser()
{
//字符串拼接,这样写就能准确获取D层的具体某个类
string ClassName = StrDB +"."+ "LoginDAL";
//定义接口类型idal,来接收返回值
Login.IDAL.LoginIDAL idal = (Login.IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);//反射加工厂的应用---------idal返回值为空
return idal;
}
}
}
接口层IDAL:
LoginIDAL类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using Login.Entity;
namespace Login.IDAL
{
public interface LoginIDAL
{
//接口函数,判断要登陆的用户名是否在数据表中存在
DataTable SelectUser(UserInfo user);
}
}
界面层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 LoginUI
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
string UserName = txtUserName.Text.Trim();
string Password = txtPassword.Text;
//验证是否为空
if (txtUserName.Text == string.Empty)
{
MessageBox.Show("请输入账号!", "登录");
return;
}
else
{
if (txtPassword.Text == string .Empty)
{
MessageBox.Show("请输入密码!", "登录");
return;
}
//#region 登录
try
{
Login.Facade.LoginFacade fLogin = new Login.Facade.LoginFacade();//实例化外观
//Facade.LoginFacade fLogin = new Facade.LoginFacade();//实例化外观
Login.Entity.UserInfo user = new Login.Entity.UserInfo();
//Entity.UserInfo user = new Entity.UserInfo();
//调用外观的方法,返回给user
user.UserName = Convert.ToString(txtUserName.Text.Trim());
user.Password = Convert.ToString(txtPassword.Text);
Boolean flag = false;
flag = fLogin.SelectUser(user);
if (flag != false)
{
MessageBox.Show("登录成功!");
}
else
{
MessageBox.Show("密码或者用户名错误");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}