光总结了C#三层登录出现的问题,还没有真正总结过三层登录实例,近来敲机房的七层登录,可谓是问题重重,当初自以为三层理解的很透彻了,现在看来还差的很多,我需要用总结来沉淀一下自己,让自己的心不那么浮躁。
简单来说,三层有别于之前有VB敲的小例子的是,三层非常好的解除了各个层之间的耦合,为以后的维护提供了极大的便利。
各个层之间的关系
U层:用户接触的层,准确来说,用户仅仅接触了一个U层。用于收集用户输入的信息以及用户的操作。
B层:根据U层用户输入的信息及操作和D层数据返回的信息,进行逻辑判断。
D层:连接数据库,接受B层消息,将用户需要的数据从数据库提取出来,返回到B层进行逻辑判断。
它们之间的引用关系为:U层引用B层,B层引用D层,各个层都引用实体层。用丹姐的包图来美化一下:
UI层很简单,就是将用户的操作传给B层。
namespace UI { public partial class Login : Form { public Login() { InitializeComponent(); } private void btnOk_Click(object sender, EventArgs e) { string UserID = txtUserID.Text.Trim();//赋值 string PassWord = txtPassWord.Text; string msg;//定义变量 msg = ""; //Model.Gobal.user = txtUserID.Text; BLL.LoginManager Agr = new BLL.LoginManager();//实例化B层 #region//验证是否为空 bool ey = Agr.Empty(UserID, PassWord); if (ey == false) { MessageBox.Show("请填写完整信息。"); return; } #endregion #region//登录 Model.UserInfo User = Agr.UserLogin(UserID, PassWord,out msg); MessageBox.Show(msg); if (msg=="登录成功。") { Model.Gobal.level = User.Level; #endregion 机房收费系统 jf = new 机房收费系统(); 机房收费系统.isRunMain = true; jf.Show(); this.Close(); } else { txtUserID.Text = ""; txtPassWord.Text = ""; txtUserID.Focus(); } } private void btnCancel_Click(object sender, EventArgs e) { this.Close(); } }
BLL层相对复杂一点,就是将U层传来的参数或D层返回的值进行逻辑判断,给出正确的操作。
namespace BLL { public class LoginManager { public Model.UserInfo UserLogin(string UserID,string PassWord,out string msg) { DAL.UserDAO uDao = new DAL.UserDAO();//引用D层的UserDAO类 Model.UserInfo User = uDao.SelectUser(UserID, PassWord);//引用实体层的SelectUser方法 if(User!=null) { //return User;//将实体user返回到U层 msg = "登录成功。"; } else { //throw new Exception("登录失败。"); msg="登录失败。";//在这如果用上面这个注释掉的语句的话,输入正确用户名密码没有关系,如果输入错误的很弹出一个非常不友好的错误提示,这在我的C#机房登录问题中有总结。 } return User; } public bool Empty(string UserID,string PassWord)//这就是验证框是是否为空的代码,我是在B层判断完返回一个bool给U层的。 { if (UserID == "" || PassWord == "") { return false; } else { return true; } } } }
DAL层主要用到的就是连接数据库,让后对数据库中的数据进行一些简单的操作后返回给B层。对于B层引用的那个DbUtil.ConnString是在D层另外一个类里面定义的
namespace DAL { class DbUtil { public static string ConnString = @"Server=XX;Database=你的数据库名字;User ID=**;Password=***";//链接数据库的字符串 } }
namespace DAL { public class UserDAO { public Model.UserInfo SelectUser(string UserID, string PassWord)//声明引用了Model层的userInfo类的SelectUser方法 { using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))//引用连接数据库的字符串,连接数据库 { SqlCommand cmd = conn.CreateCommand();//定义命令语句 cmd.CommandText = @"SELECT * FROM T_USERS WHERE UserID=@UserID AND PassWord=@PassWord"; cmd.CommandType = CommandType.Text; cmd.Parameters.Add(new SqlParameter("@UserID", UserID)); //为参数@UserID赋值 cmd.Parameters.Add(new SqlParameter("@PassWord", PassWord)); //为参数@PassWord赋值 conn.Open();//打开数据库连接 SqlDataReader Reader = cmd.ExecuteReader(); Model.UserInfo User = null; while (Reader.Read()) { if (User == null) { User = new Model.UserInfo(); } User.UserID = Reader.GetString(0);//给实体层的属性写入数据 User.PassWord = Reader.GetString(1); User.Level = Reader.GetString(2); User.Status = Reader.GetInt16(3); User.Head = Reader.GetString(4); } return User;//将实体user返回到B层 } } } }
实体层主要用于在三个层中传递实体,比如该版登录返回的类型就是实体。实体没什么好说的,用到哪个参数就在实体中创建就行,需要注意的就是实体类里面是直接对应到数据库表的,你定义的数据类型要和表中类型相一致才行。
namespace Model { public class UserInfo { public string UserID { get; set; } public string PassWord { get; set; } public string Level { get; set; } public Int16 Status { get; set; } public string Head { get; set; } } }
三层的登录和七层的登录,对比VB敲的一层机房收费系统,其实就是把类与类之间的耦合一步步变小,达到一个相对完美,符合对扩展开放,对修改关闭的原则的过程,无非就是写代码的时候看似麻烦了一点,明明可以U层直接从数据库访问数据的却非要经过那么多层,传递那么多参数,但是这在以后的维护中起到了决定性的作用。站在一个高处去看七层,其实就是把以前的一步到位,转换成参数一步步传下去的过程。
不管是VB机房,三层机房,还是七层机房,刚开始都觉得很难,后来理清楚一条线就简单了,一气呵成,现在敲七层,觉得根本不是人脑子能想出来的东西,回头看看三层,在看看VB版,它们是我一步步由难到易过来的,克服了重重困难,我相信我的七层也会在我的努力下变得简单。