开发工具与关键技术: Visual Studio 2019、C#语言、WPF、MVC三层架构
作者:邓李庆
撰写时间: 2021年2月08日
小编首先来给大家介绍一下,什么是三层架构:三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。
三层架构区分层次的目的是为了“高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。
一、 界面层(UI)
界面层提供给用户一个视觉上的界面,通过界面层,用户输入数据、获取数据。界面层同时也提供一定的安全性,确保用户不用看到不必要的机密信息。
二、 逻辑层(BLL)
逻辑层是界面层和数据层的桥梁,它响应界面层的用户请求,执行任务并从数据层抓取数据,并将必要的数据传送给界面层。
三、 数据层(DAL)
数据层定义、维护数据的完整性、安全性,它响应逻辑层的请求,访问数据。这一层通常由大型的数据库服务器实现,如Oracle 、Sybase、MS SQl Server等
三层架构的体系结构:表示层和业务逻辑层之间用对象模型的实体类对象来传递数据,业务逻辑层和数据访问层之间用对象模型的实体类对象来传递数据,数据访问层通过.NET 提供的ADO.NET组件来操作数据库,或者利用SQLServer数据库服务器的存储过程来完成数据操作,这种分层体系结构具有以下四个优点:
(1)避免了表示层直接访问数据访问层,表示层只和业务逻辑层有联系,提高了数据安全性。
(2)有利于系统的分散开发,每一个层可以由不同的人员来开发,只要遵循接口标准,利用相同的对象模型实体类就可以了,这样就可以大大提高系统的开发速度。
(3)方便系统的移植,如果要把一个 C/S 的系统变成 B/S 系统,只要修改三层架构的表示层就可以了,业务逻辑层和数据访问层几乎不用修改就可以轻松的把系统移植到网络上。
(4)项目结构更清楚,分工更明确,有利于后期的维护和升级
缺点:
(1)降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
(2)有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
(3)增加了代码量,增加了工作量
下面来搭建一个简单的三层架构登录页面,我使用的是Visual Studio 2019搭建。注:VS2017、VS2015和VS2010差不多没太大改变。首先创建一个表现层(UI):
四、 然后选择中解决方案右键添加 > 新建项目 > 找到类库创建。BLL(逻辑层)、DAL(数据层)再创建一个Model(实体数据库)如图:
搭建完成如下图:
搭建完成后需要添加引用,注:表现层(UI)引用BLL和Model,逻辑层(BLL)引用DAL和Model,数据访问层(DAL)引用Model。如何图:
然后在逻辑层(BLL)创建一个类,取名为“UserService”,再到数据访问层(DAL)也创建一个类“DALMethod”,然后再到实现实体数据库(Model),创建一个类“UserLogin”
到数据访问层(DAL)类“DALMethod”里面写上查询语句:
using System;
using System.Data;//创建表类型的变量需要引用的空间
using System.Data.SqlClient;//创建数据库连接需要引用的空间
namespace ItcastCater.DAL//数据访问层
{
public class DALMethod
{
//连接字符串
public static readonly string strConnect = @"Data Source=***;Initial Catalog=SQL;User ID=***;Password=***";
///
/// 查询数据表
///
/// SQL语句
/// SQL语句中的参数
/// 查询出一条数据
public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] ps)
{
SqlConnection con = new SqlConnection(strConnect);
using (SqlCommand cmd = new SqlCommand(sql, con))
{
if (ps != null)
{
cmd.Parameters.AddRange(ps);
}
try
{
con.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception)
{
con.Close();
con.Dispose();
throw;
}
}
}
}
}
到逻辑层(BLL)类“UserService”里面写上处理的语句:
using ItcastCater.DAL;
using ItcastCater.Model;
using System;
using System.Data.SqlClient;
namespace ItcastCater.BLL//业务逻辑层
{
public class UserService
{
//获取用户信息
public UserLogin GetUser(string strAccount, string strPassword)
{
//查询语句
string sql = "select * from PW_User where Account=@Account";
//实例化对象数组(序列化参数)
SqlParameter[] param = new SqlParameter[]{
//定义传递参数,以及传递参数的类型
new SqlParameter("@Account",strAccount),
new SqlParameter("@Password",strPassword),
};
// 执行
UserLogin user = new UserLogin();
//调用数据访问层
using (SqlDataReader sdr = DALMethod.ExecuteReader(sql, param))
{
while (sdr.Read())
{
user.UserID = Convert.ToInt32(sdr["UserID"]);
user.Account = sdr["Account"].ToString();
user.Password = sdr["Password"].ToString();
user.Name = sdr["Name"].ToString();
user.Time = sdr["Time"].ToString();
user.Employ = Convert.ToBoolean(sdr["Employ"]);
}
return user;
}
}
}
}
到表现层(UI)在登录按钮方法中写:
private void Button_Click(object sender, RoutedEventArgs e)
{
try
{
//实例化逻辑层
BLL.UserService Service = new BLL.UserService();
//获取页面数据判断是否为空
if (Account.Text.Trim() != string.Empty && Password.Password.Trim() != string.Empty)
{
//获取页面数据的账号
string strAccount = Account.Text.Trim();
//将用户输入的密码进行AES256加密法加密
string strPassword = AESEncryptHelper.Encrypt(Password.Password.Trim());
//调用逻辑层
UserLogin user = Service.GetUser(strAccount, strPassword);
//判断数据是否与数据库的数据相同
if (user.Account == strAccount || user.Password == strPassword || user.Employ == true)
{
MessageBox.Show("登入成功!!!", "提示", MessageBoxButton.OK);
//提取返回的数据(用户姓名)
string strName = user.Name.ToString().Trim();
//实例化主页面并赋值
MainWindow main = new MainWindow(strName);
//打开另外一个窗口
main.Show();
//关闭当前窗口
this.Close();
}
else
{
MessageBox.Show("该用户不存在!!!", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
else
{
MessageBox.Show("账号或密码不能为空!", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception)
{
MessageBox.Show("请连接网络!", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
}