首先
在写七层登录之前要先把它的包图画出来,通过图之间的关系决定后续在敲代码的时候引用关系,其实在写这个的时候自己也没有多少经验,只能从网上找别人写的来照猫画虎,不过最后还是把它们之间的关系理清了,后面的工作就是对各层之间实现功能然后引用就行了。
代码部分
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层之间的数据传递。
//工厂层
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; }
}
}