-
什么是三层?
三层又分为物理划分和逻辑划分
物理划分 | 逻辑划分 |
显示层/业务层/数据层 | UI,BLL,DAL |
-
每层的功能是什么?
UI层(表现层):
主要用于存放与用户交互的展示页面,原则: 用户至上,兼顾简洁
注意: 在一般使用中,UI层需要添加一个对BLL层的对象的引用,使得UI层和BLL层之间建立连接。
BLL层(业务逻辑层):
主要用于存放针对具体问题对数据进行逻辑处理的代码
从DAL中获取数据,以供UI显示, 从UI中获取用户指令和数据,执行业务逻辑
DAL(数据访问层):
主要用于存放对原始数据进行操作的代码
DAL只提供基本的数据访问,不包含任何业务相关的逻辑处理
-
三层之间的关系
在三层结构中,各层之间相互依赖,表示层依赖于业务逻辑层,业务逻辑层依赖于数据访问层
-
为什么要使用三层,它有什么好处?
三层中耦合度很低,无论哪层需要发生改变,仅仅需要改变该层,不需要更改整个系统
层次清晰,每层之间耦合度低。
- 举个例子:
服务员:仅仅用来接待客人
厨师:仅仅负责客人点的菜
采购员:按客人点菜的要求采购食材
他们自己负责自己的工作,服务员只需要知道客人的需求,不需要了解厨师是如何做菜的,也不需要了解采购员
厨师不需要了解接待了哪个客户,只需要知道做什么菜
采购员也不需要知道具体的客户也不需要知道怎么做菜,只需要知道需要买的食材。
具体过程:
顾客直接和服务员打交道,顾客和服务员(UI层)说:我要一个炒茄子,而服务员不负责炒茄子,她就把请求往上递交,
传递给厨师(BLL层),厨师须要茄子,就把请求往上递交,传递给採购员(DAL层),
做好炒茄子后,又传回给服务员,服务员把茄子呈现给顾客。
不知道大家有没有在视频中发现一个事情就是: 虽然我们学习的是三层架构,但是莫名奇妙的多出了一个 Model 模板
其实这个模板起到的“上窜下蹦”的作用,贯穿于三层,在三层之间传递参数
---------三层登陆分析:
学习过视频,然后跟着老师敲了一个三层的登陆窗体
1.先来看一下UI层:
public void button1_Click(object sender, EventArgs e)
{
//用来获取登陆界面的信息
string userName = txtUserName.Text.Trim();
string password = txtPassword.Text;//密码就不需要添加trim 因为密码里可能会有空格
//需要和逻辑B层建立连接
LoginManager mgr = new LoginManager();//相当于构造了一个实例,实例化
//把信息传递给建立的模型中
UserInfo user = mgr.UserLogin(userName, password);
//uI层返回业务层传递得数据给用户
MessageBox.Show("登录用户:" + user.UserName);
}
UI层:
在我们使用MessageBox.Show方法的时候需要在命名空间中 加载:
using System.Windows.Forms;
如果这个语句报错,那么我们需要在项目引用中加入一个插件:
2.BLL层:
public class LoginManager
{
public LoginModel.UserInfo UserLogin(string userName, string password)
{
//实例化D层对象,传输数据
UserDAO uDao = new UserDAO();
//通过user表去查询是否可以登陆成功,是否有用户信息
LoginModel.UserInfo user=uDao.SelectUser(userName, password);
//如果用户信息不为空,那么就需要在ScoreDAO表中更新数据
if (user != null)// login successfully;
{
//实例化一个sDao的实例
LoginDAL.ScoreDAO sDao = new LoginDAL.ScoreDAO();
//通过sDao类的UpdateScore函数来实现更新的操作
sDao.UpdateScore(userName, 10);
return user;
}
else
{
throw new Exception("登陆失败");//作用是抛出错误,用这个抛出错误的原因让使用者知道为什么
}
}
}
具体代码的含义已经在注释中有写。
throw new Exception("登陆失败"),当我们输入的用户名或者密码不符合要求的时候就会跳到这里,表示出现错误
当然我们也可以用 Messagebox.show("登陆失败") 来代替。
3.DAL层:
using System.Data.SqlClient;
/*
表示在你的代码中引入微软发布的sqlserver数据库的ado.net程序集,引入后,
你就可以使用SqlConnection、SqlCommand等数据库对象来访问sqlserver数据库。
*/
namespace LoginDAL
{//登陆积分
public class ScoreDAO
{
public void UpdateScore(string userName, int value)
{
//SqlConnection 用来连接数据库
using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
{
//实例化一个cmd类对象来对数据库进行存储操作
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)";
//cmd.Parameters.Add(new SqlParameter(@"ID", ID));
//将 userName 传递给 userName
cmd.Parameters.Add(new SqlParameter(@"userName", userName));
//将value传递给Score;
cmd.Parameters.Add(new SqlParameter(@"Score", value));
conn.Open();
//开始执行 cmd 开始插入
cmd.ExecuteNonQuery();
}
}
}
public class UserDAO
{
public LoginModel.UserInfo SelectUser(string userName, string password)
{
using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"SELECT ID,UserName,Password,Email FROM USERS WHERE UserName=@UserName
AND Password=@Password";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("@UserName",userName));
cmd.Parameters.Add(new SqlParameter("@Password", password));
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
LoginModel.UserInfo user = null;
while (reader.Read())
{
if (user == null)
{
user = new LoginModel.UserInfo();
}
user.ID = reader.GetInt32(0);
user.UserName = reader.GetString(1);
user.Password = reader.GetString(2);
if (!reader.IsDBNull(3))
{
user.Email = reader.GetString(3);
}
}
return user;
}
}
}
知识点:
- 1.C#中写sql 语句前为什么要加一个@ 符号
sql语句 前面加@可以防止换行后C#报错。@后面不管换了多少行,都表示是一个字符串。
- 2.using System.Data.SqlClient; //这个语句的作用是什么?
/*
表示在你的代码中引入微软发布的sqlserver数据库的ado.net程序集,引入后,
你就可以使用SqlConnection、SqlCommand等数据库对象来访问sqlserver数据库。
*/
- 3. using()的作用:
在using ()中建的对象,会在{ }结束的时候自动关闭和释放,不需要你手动进行。
这样你不用每次都要去调用conn.Close(),或者conn.Dispose()了,这样能减少人为引入Bug的机会。相当于定义了一个范围,当代码执行完毕就会跳出大括号,而跳出大括号之后就等于出了using的这个区域,
4.模板Model:
namespace LoginModel
{
public class UserInfo
{
//一系列属性
public int ID { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
}
}
用来接受参数,并且传参。