您的位置:首页 > 其它

三层学习之初相识

2016-05-12 07:30 260 查看

唏嘘

    这几天学习了王继彬老师的三层视频,看完之后很是沉默了,我终于明白之前老师和师哥师姐们对我们做的学习型项目的评价了:能跑是能跑,一不能调试二不能维护,出错就完蛋。

宏观认知

    三层学习,用我现在的目光来看,出现在我视野中的只有解耦这一终极奥义。通过DAL(数据访问层,Data Access Layer)、BLL(业务逻辑层,Business Logic Layer)和UI(显示层,Display layer)以及Model这个数据传输者的配合实现对数据库访问这一功能的解耦,使得代码的扩展性和维护性有了质的飞越。



结构

    结构这方面,学习三层需要从物理和逻辑两方面进行理解。物理方面的基础显示层、业务层和数据层,其对应的就是PC客户机、应用服务器和数据服务器了。而在逻辑方面,三层是从UI、BLL和DAL这三方面进行的解耦工作。学过三层之后,仔细的回顾了下之前自己写的那些数据库访问的代码:不管是DAL层还是BLL层,代码都挤在了UI层;也就是说,一个UI层领着一份工资却干着三个人的工作,效率之低可想而知。

引用

    三层模式能完成解耦工作的一个重要原因就在于DAL、BLL和UI之间引用的巧妙使用。双刃剑用得好可以杀敌,可用不好同样可以伤己,引用也是如此。我们在使用引用完成三层模式的功能时,切忌相互引用从而导致循环依赖项情况的出现,举例如下:



    所以我们在使用引用时,应避免在A已经引用B后,再设置B引用A这种情况的出现。

职责

    在学习三层的时候,我认为三层把单一职责原则和职责链模式的思想发挥的算式淋漓尽致了:每一层只负责自己的那部分,对程序的其余部分绝不过问。也正因为如此,三层模式得以职责分明,从而很好地实现了解耦的目的。
    DAL:只负责基本的数据库访问;
    UI:只负责显示和采集用户操作;
    BLL:负责处理业务逻辑、获取UI的操作指令、向DAL递交数据访问请求以及向UI返回数据。
    在这里我向加入一个Model(下面代码将会给出例子),Model可以负责在UI、BLL和DAL之间进行必要的数据传递,从而将解耦程度再次提高。

代码展示

DAL

UserDAO

<span style="font-family:KaiTi_GB2312;font-size:24px;">namespace Login.DAL
{
public class ScoreDAO
{
public void UpdateScore(string userName, int value)
{
using (SqlConnection conn = new SqlConnection(DbUtil.connString))
{
//建立数据库连接
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)";
cmd.Parameters.Add (new SqlParameter ("@UserName",userName ));
cmd.Parameters.Add(new SqlParameter("@Score",value ));

conn.Open();        //打开数据库连接
//cmd.ExecuteNonQuery();
}
}
}
}</span>


ScoreDAO

<span style="font-family:KaiTi_GB2312;font-size:24px;">namespace Login.DAL
{
public class UserDAO
{
//public Login.Model .UserInfo  SelectUser(string userName, string password)
//{
//    throw new NotFiniteNumberException();
//}
public Login.Model.UserInfo SelectUser(string userName, string password)
{
using (SqlConnection conn = new SqlConnection(DbUtil.connString))       //关键字using,允许在打开数据库链接后,不用手动关闭连接
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"SELECT ID, UserName, Password, Email
FROM USERS WHERE UserName=@UserName AND Password=@Password";        //UserName=@UserName 可以实现数据库中对应字段存储的是什么属性,就返回什么属性的功能
cmd.CommandType = 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;
//Login.Model.UserInfo uesr = null;
while (reader.Read ())
{
if (user ==null )
{
//user = new Login.Model.UserInfo();
user = new Login.Model.UserInfo();
}
//reader.GetInt32(0);
//reader.GetString(1);
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;
}
}
}
}</span>


DbUtil

<span style="font-family:KaiTi_GB2312;font-size:24px;">namespace Login.DAL
{
class DbUtil
{
//public static string connString = @"Server=JokerSky; Database=Login; User ID=sa; Password=1";
public static string connString = @"Server=JokerSky\SQLEXPRESS;Initial Catalog=Login;User ID=sa;Password=1";
}
}</span>


BLL

<span style="font-family:KaiTi_GB2312;font-size:24px;">namespace Login.BLL
{
public class LoginManager
{
public Login.Model.UserInfo  UserLogin(string userName,string password)
{

//Login.DAL.UserDAO uDao= new Login.DAL.UserDAO();
//uDao.SelectUser(userName,password );
//Login.DAL.UserDAO uDao = new Login.DAL.UserDAO();
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);     //int value 的生命,使得积分可以改动
return user;
}
else            //登录失败
{
throw new Exception("登录失败");

}

}
}
}
</span>


UI

<span style="font-family:KaiTi_GB2312;font-size:24px;">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;

//向BLL层传递数据
Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();
Login.Model.UserInfo user = mgr.UserLogin(userName ,password );        //此处可能有问题

MessageBox.Show("登录用户:"+user.UserName );

}
}
}
</span>


Model

<span style="font-family:KaiTi_GB2312;font-size:24px;">namespace Login.Model
{
public class UserInfo
{
public int ID { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }

}
}
</span>


    PS:以上四部分代码注意命名空间的引用,Using System.Data和           Using System.Data.SqlClient。

Summary

    接触了三层模式,才知道自己之前做的学习型项目是有多“金贵”。而在三层学习的过程中,自己又对之前的单一职责原则、依赖倒转原则、职责链模式、构造函数和封装的有了更加深刻的理解。但是自己在编程的道路上还是太稚嫩,幸运的是在我们这个温暖向上的大家庭中,我还在成长。
感谢您的宝贵时间,祝您生活愉快,谢谢~~
——joker
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: