首先
在写七层登录之前要先把它的包图画出来,通过图之间的关系决定后续在敲代码的时候引用关系,其实在写这个的时候自己也没有多少经验,只能从网上找别人写的来照猫画虎,不过最后还是把它们之间的关系理清了,后面的工作就是对各层之间实现功能然后引用就行了。
代码部分
UI层:主要用于收集用户输入的数据然后传给外观层,再由外观层传给B层进行相应的判断。
public partial class frmLogin : Form { public frmLogin() { InitializeComponent(); } private void btnLogin_Click(object sender, EventArgs e) { //判断输入不能为空 if (txtUserName.Text.Trim() == "") { MessageBox.Show("请输入用户名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } if (txtPassword.Text == "") { MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } try { //实例化一个用户实体user Entity.UserInfo user = new Entity.UserInfo(); //接受控件传来的用户信息 user.UserID = Convert.ToInt32 (txtUserName.Text.Trim()); //接受控件传来的密码信息 user.PassWord = txtPassword.Text; //实例化外观 Facade.LoginFacade FLogin = new Facade.LoginFacade(); //定义一个bool型的变量,用于查看接收是否查找成功 Boolean flag = false; //调用外观的方法,返回给flag flag = FLogin.SelectUser(user); //判断是否登陆成功 if (flag != false) { MessageBox.Show("登录成功!"); this.Hide(); this.DialogResult = System.Windows.Forms.DialogResult.OK; //实例化一个窗体 Form a = new Form(); a.Show(); } else { MessageBox.Show("用户名或密码错误!"); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Facade层:运用外观层的目的是降低U层和B层之间的耦合,U层和B层之间的联系只需要通过Facade层的接口就行了,U层无需知道B层内部有哪些方法。外观层接收U层传来的数据,然后调用B层的方法对信息进行验证。
//外观层 public class LoginFacade { //将数据User从UI层传入BLL层,提供返回值给flag public Boolean SelectUser(Entity.UserInfo user) { bool flag; //实例化一个B层 BLL.LoginBLL userBLL = new BLL.LoginBLL(); flag = userBLL.UserBLL(user); return flag; } }
BLL层:B层主要是进行逻辑判断的,调用工厂中的方法创建相应的接口。
//业务逻辑层 public class LoginBLL { //判断用户是否存在 public bool UserBLL(Entity.UserInfo user) { //实例化工厂 Factory.LoginFactory fact = new Factory.LoginFactory(); //调用工厂中的方法,实例化一个实现接口的内部类,将反射结果赋个idal IDAL.LoginIDAL idal = fact.CreateUser();//登陆中,此时的idal反射的是dal中的loginDAL类 //接受D层的返回值 DataTable table = idal.SelectUser(user); bool flag; //返回数据表类型,如果行数=0,说明没有符合该账号密码的用户 if (table.Rows.Count==0) { flag = false; } else { flag = true; } //返回数值 return flag; } }
Factory层:通过配置文件和抽象工厂我们可以实现不更改代码,换一下配置文件中的value值就可以更换数据库了。Factory还需要完成的工作就是定义一个接口调用接口层,实现BLL层和DAL层之间的数据传递。
1. //工厂层 public class LoginFactory { //接受来自配置文件的数据,明确工厂要链接那一层 string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"]; //应用反射来获取被调用的DAL层的具体操作类 public IDAL.LoginIDAL CreateUser() { //明确具体操作类 string className = StrDB + "." + "LoginDAL"; //反射加工厂的应用-将在DAL层中用到的具体类反射到接口,说明那个类实现了这个接口 return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(className); } }
IDAL层:接口层是用于定义一个统一的接口,解除B层和D层的耦合。
public interface LoginIDAL { //放置接口函数,判断要登陆的用户是否在数据表中存在 DataTable SelectUser(Entity.UserInfo user); //DataTable Selectuser(UserInfo user); }
DAL层:实现接口层定义的接口。
public class LoginDAL:IDAL.LoginIDAL { public DataTable SelectUser(Entity.UserInfo user) { //实例化数据操作类,进行数据查询,并获取返回值 SQLHelper sqlHelper = new SQLHelper(); //选在要查询的数据类型,作为sqlCommand的参数 SqlParameter[] sqlparams = { new SqlParameter("@UserName", user.UserID), new SqlParameter("@Password", user.PassWord)}; //查询语句 string sql = "select * from Users where UserName=@UserName AND Password=@Password"; //将查询语句和要查询的数据传入sqlHelper类中进行查询操作 DataTable table = sqlHelper.ExecuteQuery(sql, sqlparams, CommandType.Text);//CommandType.Text解释SQL文本命令的字符串 return table; } }
SQLHelpers:可以建立在D层下,也可以单独成为一个类
SQLHelper类封装了重复写的一些数据库连接的代码。封装后通过给方法传递参数来访问数据库。
public class SQLHelper { private SqlConnection conn = null;//定义数据连接操作 private SqlCommand cmd = null;//指定能在数据库上执行的操作 private SqlDataReader sdr = null;//定义一个读取数据流的变量,从数据库中读取 public SQLHelper() { string connStr = ConfigurationManager .AppSettings ["connStr"];//ConnStr配置文件中连接数据的关键字(字符串) conn = new SqlConnection(connStr);//实例化一个连接 } //将连接的数据库打开 private SqlConnection GetConn() { if (conn.State==ConnectionState.Closed)//如果连接状态为关闭,则打开 { conn.Open(); } return conn; } //只显示运行代码,SQLHelper类中的其他数据库操作省略 public DataTable ExecuteQuery(string cmdText,SqlParameter[] paras,CommandType ct) { //实例化一个数据表 DataTable dt = new DataTable(); //实例化出一个数据操作 cmd = new SqlCommand(cmdText, GetConn());//cmdText为传进来的SQL命令,GetConn为一个打开状态的数据库连接 cmd.CommandType = ct; cmd.Parameters.AddRange(paras);//将要查询的数据放入查询语句中 using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { //通过提供的sqlDataReadere,对表进行操作 dt.Load(sdr); } return dt; } }
Entity层:主要是用来在各层中传递数据。
上面的包图把引用关系阐述的已经很明白,那么开始实践,同时与三层相同的提醒,注意命名是否一致。
public class UserInfo { //定义用户ID属性 private int userid; public int UserID { get { return userid; } set { userid = value; } } //定义用户密码PassWord属性 private string password; public string PassWord { get { return password; } set { password = value; } } }