昨天验收三层架构,师父问了几个很简单很基础的问题,我回答的不是很好,而且对三层架构的理解和解释不是很清楚,于是下去之后我又重新研究了一下三层架构,从u层开始,一行代码一行代码的捋了一遍,现在总算理清楚了。
首先,我先画了一个图来看一看三层架构是如何进行数据的请求和工作的。
下面我来讲一下三层代码的流程,代码是如何跑起来的:
1、在u层输入用户名,密码,登录。
将输入的用户名密码赋值给对应的userName和password
string userName = txtUserName.Text.Trim();
string password = txtPassword.Text.Trim();
2、进入BLL层,LoginManager进行逻辑判断
Login.DAL.UserDAO uDao = new Login.DAL.UserDAO();
Login.Model.UserInfo user = uDao.SelectUser(userName,password);
3、然后进入DAL层访问数据(进入数据库)
public Login.Model.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 = System.Data.CommandType.Text;
cmd.Parameters.Add(new SqlParameter("@Username",userName));
cmd.Parameters.Add(new SqlParameter("@Password",password));
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
Login.Model.UserInfo user = null;
while (reader.Read())
{
if (user==null)
{
user = new Login.Model.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;
}
}
4、数据匹配完成之后再次返回BLL层,进行逻辑判断执行逻辑语句,将对应的分数更新。(更新数据需要访问DAL层,所以再次进入DAL层)
public void UpdateScore(string userName, int value)
{
using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"INSERT INTO SOCRES(UserName,Score) Values(@UserName,@Score)";
cmd.Parameters.Add(new SqlParameter("@UserName", userName));
cmd.Parameters.Add(new SqlParameter("@Score",value));
conn.Open();
cmd.ExecuteNonQuery();
}
}
5、数据匹配没有问题之后返回BLL层执行相应代码,进行逻辑判断
public Login.Model.UserInfo UserLogin(string userName, string password)
{
Login.DAL.UserDAO uDao = new Login.DAL.UserDAO();
Login.Model.UserInfo user = uDao.SelectUser(userName,password);
if (user!=null)
{
Login.DAL.ScoreDAO sDao = new Login.DAL.ScoreDAO();
sDao.UpdateScore(userName,10);
return user;
}
else
{
//throw new Exception("登录失败");
return null;
}
}
6、最后返回u层,显示结果。
private void BtnLogin_Click(object sender, EventArgs e)
{
string userName = txtUserName.Text.Trim();
string password = txtPassword.Text.Trim();
Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();
Login.Model.UserInfo user=mgr.UserLogin(userName,password);
//MessageBox.Show("登录用户:" + user.UserName);
if (user!=null)
{
MessageBox.Show("登录用户:" + user.UserName);
}
else
{
MessageBox.Show("登录失败");
}
}
这个代码的流程呢,也就是和上面的图是相对应的。
那么问题来了,每一层都各负其责,那么如何将三层联系起来呢?
1、单项引用
2、实体层来了(当然实体层的作用不止这些)
Entity(实体层):它不属于三层中的任一层,但是它是必不可少的一层。
entity在三层架构中的作用:
1、实现面向对象思想中的“封装”
2、贯穿于三层,在三层之间传递数据,来连接三层
3、我们现在可以这样理解:每张数据表对应一个实体,即每个数据表中的字段对应实体中的属性。(注:当然,事实上不是这样。为什么?1>、可能我们需要的实体在数据表中并不存在;2>、我们完全可以将所有数据表中的所有字段放在一个实体里)
4、每一层(UI→BLL→DAL)之间的数据传递是靠变量或实体作为参数来传递的,这样就构造了三层之间的联系,完成了功能的实现。
综上所述,三层及实体之间的依赖关系:
思想来源于生活:
服务员:只管接待客人;
厨师:只管做客人点的菜;
采购员:只管按客人点菜的要求采购食材;
他们各负其职,服务员不用了解厨师如何做菜,不用了解采购员如何采购食材;厨师不用知道服务员接待了哪位客人,不用知道采购员如何采购食材;同样,采购员不用知道服务员接待了哪位客人,不用知道厨师如何做菜。
他们三者是如何联系的?
比如:厨师会做:炒茄子、炒鸡蛋、炒面——此时构建三个方法( cookEggplant()、cookEgg()、cookNoodle())
顾客直接和服务员打交道,顾客和服务员(UI层)说:我要一个炒茄子,而服务员不负责炒茄子,她就把请求往上递交,传递给厨师(BLL层),厨师需要茄子,就把请求往上递交,传递给采购员(DAL层),采购员从仓库里取来茄子传回给厨师,厨师响应cookEggplant()方法,做好炒茄子后,又传回给服务员,服务员把茄子呈现给顾客。
这样就完成了一个完整的操作。
在此过程中,茄子作为参数在三层中传递,如果顾客点炒鸡蛋,则鸡蛋作为参数(这是变量做参数)。如果,用户增加需求,我们还得在方法中添加参数,一个方法添加一个,一个方法设计到三层;何况实际中并不止设计到一个方法的更改。所以,为了解决这个问题,我们可以把茄子、鸡蛋、面条作为属性定义到顾客实体中,一旦顾客增加了炒鸡蛋需求,直接把鸡蛋属性拿出来用即可,不用再去考虑去每层的方法中添加参数了,更不用考虑参数的匹配问题。