刚开始接触三层的时候没头绪,虽然知道它们之间的引用关系,可是还是感觉很混乱,所以上网看了看博客,决定先从画图入手。从包图——>类图——>时序图(逻辑)——>代码,一步步的重新做!
一、包图
为什么要有实体层?没有实体层可以吗?为什么不叫四层,而叫三层呢?
实体层的作用是便于层与层之间数据的传递,每个实体对象与数据库里的表示一一对应的。对于大量的数据来说,就可以直接通过实体对象用Get(),Set()方法将字段提取出来,这比临时在创建变量要省事。就相当于利用面向对象的思想,将大量的数据进行封装后在进行传递。
例如:
AddUser(UserID,UserName,UserPassword)
用了实体层,将这些字段封装到UserInfo类中,可以写为AddUser(UserInfo),这样就省事多了。
并不是一定要有实体层,如果只有少量数据, 例如机房收费系统中,查询某个卡号对应的学生,可以通过CardID作为参数来进行传递,也就没有必要用实体层进行传递了。
实体层是为了数据传递提供方便,只是一个类,并无实际作用,可有可无,所以不可以和UI,DAL,BLL一样作为层来说。
二、类图
1、实体层 UserInfo类
2、D层:DbUtil类和UserDAO类
3、B层:LoginManager类
4、U层:FrmLogin类
三、时序图
四、代码
1、Entity层:UserInfo类
定义字段,获取字段的Get()与Set()方法,与数据库中的Users表是对应的,方便数据的传递
namespace LoginModel { //数据库表的映射 public class UserInfo { private string username; public string UserName { get { return username; } set { username = value; } } private string password; public string PassWord { get { return password; } set { password = value; } } public UserInfo(string username, string password) { this.username = username; this.password = password; } } }
2、D层:
(1)DbUtil类:
namespace LoginDAL { /// <summary> /// 创建连接数据库字符串 /// </summary> class DbUtil { public static string ConnString = @"server=bill\BILLSQL;dataBase=Users;user id=sa;password=123456"; } }
(2)UserDAO类:
主要用于提供数据库的基本访问,供BLL调用。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; namespace LoginDAL { public class UserDAO { //查询用户 public LoginModel.UserInfo SelectUser(string username, string password) { using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))//创建SQL数据库打开连接 { SqlCommand cmd = conn.CreateCommand(); //创建并返回一个与 SqlConnection 关联的 SqlCommand 对象 cmd.CommandText = @"select username,password from user_Info where [email protected] and [email protected]";//获取数据源执行的查询语句 cmd.CommandType = CommandType.Text;//设置一个值用来解释CommandText属性 //将指定的SqlParameter添加到SqlParameterCollection中 cmd.Parameters.Add(new SqlParameter("@username", username)); cmd.Parameters.Add(new SqlParameter("@password", password)); conn.Open();//打开数据库连接 SqlDataReader reader = cmd.ExecuteReader();//将 CommandText 发送到 Connection 并生成一个 SqlDataReader LoginModel.UserInfo user = null; //使 SqlDataReader 前进到下一条记录 while (reader.Read()) { if (user == null) { user = new LoginModel.UserInfo(); } user.UserName = reader.GetString(0); user.PassWord = reader.GetString(1); } return user; } } } }
3、B层:LoginManager类
处理业务逻辑,主要包括判断用户名与密码的是否为空,以及从D层中获取的数据传递给实体层。
namespace LoginBLL { public class LoginManager { public LoginModel.UserInfo UserLogin(string username, string password) { //throw new NotImplementedException(); LoginDAL.UserDAO uDAO = new LoginDAL.UserDAO(); //用户名不能为空 if (username == null) { throw new Exception("请输入用户名"); } //密码不能为空 if (password == null) { throw new Exception("请输入密码"); } LoginModel.UserInfo user = uDAO.SelectUser(username, password); if (user != null) { return user; } else { throw new Exception("登录失败"); } } } }
4、U层:FrmLogin类
主要是界面命令以及操作,接收B层传来的数据。
namespace LoginUI { public partial class FrmLogin : Form { public FrmLogin() { InitializeComponent(); } private void btnLogin_Click(object sender, EventArgs e) { string username = txtUserName.Text.Trim() ; string password = txtPassWord.Text; try { LoginBLL.LoginManager mgr = new LoginBLL.LoginManager(); LoginModel.UserInfo user = mgr.UserLogin(username, password); MessageBox.Show("登录用户:" + user.UserName); } catch (Exception err) { MessageBox.Show(err.Message.ToString()); } } private void btnCancel_Click(object sender, EventArgs e)//卸载窗体 { Close(); } } }
五、收获
虽然理论理解了理论,但是有的代码还是不太理解,尤其是传递数据的那块,调试的时候发现是这样的:在界面输入用户名和密码——>B层——>D层——>实体层——>D层——>B层——>界面显示登录成功!
用户输入用户名和密码后,执行B层代码判断用户名和密码是否为空,实例化LoginManager类,调用它的UserLogin方法;跳到B层,实例化UserDAO类,并调用它的SelectUser方法;调到D层,创建连接数据库对象,……到实体层这又乱了,正在看这篇博客的大神们,你们帮帮忙吧!