需要做的工作:
一、定好命名格式规范:
1. 解决方案:ComputerChargeSolution
2. 七层:UI-Facade-BLL-DAL(里面的类SQLHelper)-Factory-IDAL-Entity
3. 登录:
七层的类和接口名:
LoginUI-LoginFacade-LoginBLL-LoginDAL-LoginFactory-ILoginIDAL-UserInfo
窗体frmLogin
用户名字txtUserName
用户密码txtPassWord
登录btnOK
取消btnCancel
二、清楚七层关系
他们之间的引用关系:
SQLHelper建立在D层下
UI:引用Facade Entity
Facade:引用BLL Entity
BLL:引用Factory IDAL Entity
Factory:引用IDAL
IDAL:引用Entity
DAL:引用IDAL Entity
注意:接口层的命名为了区分需要在前面加上I,所以IDAL命名登录子类时,为ILoginIDAL
代码实现
配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<appSettings>
<add key ="Connstr" value ="server=邢美玲-PC\SQLEXPRESS; database =charge_sys;User ID =sa; Password=123456"/>
<add key ="DB" value ="DAL"/>
</appSettings>
</configuration>
Entity层
namespace Entity
{
public class UserInfo
{
private int _userid;
public int userID
{
get { return _userid; }
set { _userid = value; }
}
private string _password;
public string password
{
get { return _password; }
set { _password = value; }
}
private string leve1;
public string Leve1
{
get {return leve1;}
set {leve1=value;}
}
}
}
UI层:
实例化实体层Entity为user通过Entity传递登录输入的数据通过Facade.LoginFacade Flogin = new Facade.LoginFacade();给外观层,然后通过外观层Facade传送到其他层进行查询验证,再返回flag = Flogin.SelectUser(user);
private void btnOK_Click(object sender, EventArgs e)
{
try
{
Entity.UserInfo user = new Entity.UserInfo();
user.userID = Convert.ToInt32(txtUserName.Text.Trim());
user.password = txtPassWord.Text.Trim();
Boolean flag = false;
Facade.LoginFacade Flogin = new Facade.LoginFacade();//传递给外观层
flag = Flogin.SelectUser(user);
if (flag!=false )
{
//this.Hide ()
MessageBox.Show("登录成功!");
}
else
{
MessageBox.Show("验证错误,重新输入");
}
}
catch (Exception ex)
{
MessageBox.Show(ex .Message );
}
}
Facade层:通过实例化BLL层的LoginBLL传值给userBLL
public class LoginFacade
{
public Boolean SelectUser(Entity.UserInfo userInfo)
{
bool flag;
BLL.LoginBLL userBLL = new BLL.LoginBLL();//实例化
flag = userBLL.UserBLL(userInfo);//传值给UserInfo到B层
return flag;
}
}
BLL层
目的:就是从D层的数据库的值或表传到B层
过程:从D层执行查询的内容,传到B进行逻辑判断传出
问:那么为什么有IDAL接口层的存在?为什么有Factory工厂类的存在?见下面
public class LoginBLL
{
public bool UserBLL(Entity.UserInfo userinfo)
{
Factory.LoginFactory fact = new Factory.LoginFactory();
IDAL.ILoginIDAL idal = fact.CreateUser();
DataTable table = idal.selectUser(userinfo);
bool flag;
if (table.Rows.Count ==0)
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
}
Factory层:
这里用到了抽象工厂的反射
先说一下抽象工厂:提供一个创建一系列相关的对象的接口,无需指定他们的具体类。
所以在B和D层之间有一个IDAL层来当这个接口,具体的类是在D层中指定的。
什么是反射:可以通过封装类方便进行修改等操作。封装的是谁?是调用不同类型数据库的方法,便于对数据库类型进行修改。
在配置文件中<add key ="DB" value ="DAL"/>
可以修改我们需要的数据库类型
public class LoginFactory
{
string strDB = ConfigurationManager.AppSettings["DB"];
public IDAL.ILoginIDAL CreateUser()
{
string ClassName = strDB + "." + "LoginDAL";//反射
return (IDAL.ILoginIDAL)Assembly.Load(strDB).CreateInstance(ClassName);
}
}
IDAL接口层:
声明接口,创建方法SelectUser
回答问1:接口层在B和D层之间,D层直接用接口层创建好的方法来执行SQL语句,D层执行完查询之后return到B层
public interface ILoginIDAL
{
DataTable selectUser(Entity.UserInfo UserInfo);
}
DAL层的LoginDAL类:执行接口层SelectUser的方法,查到的值返回B
public class LoginDAL : IDAL.ILoginIDAL
{
public DataTable selectUser(Entity.UserInfo UserInfo)
{
SQLHelper sqlHelper = new DAL.SQLHelper();
SqlParameter[] sqlParams = { new SqlParameter("@userid",UserInfo .userID ),new SqlParameter ("@Password",UserInfo .password ) };
string sql = "SELECT * FROM User_Info WHERE userID=@userid AND PWD =@Password";
DataTable table= sqlHelper.ExecuteQuery(sql, sqlParams, CommandType.Text);
return table;
}
}
SQLHelpter类
public class SQLHelper
{
private SqlConnection conn = null;
private SqlCommand cmd = null;
private SqlDataReader sdr = null;
public SQLHelper()
{
string connstr = ConfigurationManager.AppSettings["connstr"];
conn = new SqlConnection(connstr);
}
private SqlConnection Getconn()
{
if (conn.State== ConnectionState.Closed)
{
conn.Open();
}
return conn;
}
public DataTable ExecuteQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
DataTable dt = new DataTable();
cmd = new SqlCommand(cmdText, Getconn());
cmd.CommandType = ct;
cmd.Parameters.AddRange(paras);
using (sdr =cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
dt.Load(sdr);
}
return dt;
}
}
错误分析
错误一;启动开始后弹出的错误
说明是启动项除了问题,原因是在建立UI层的时候建成了类而不是Window输出程序。
类似的错误:CS5001 C# 程序不包含适合于入口点的静态 “Main” 方法的错误
错误二:点击登录按钮后错误
修改D层的文件输出路径即可。
小结:感谢阅读指正