正确的程序流程在3层设计时登录
本文关键字:3层 登录 程序 | 更新日期: 2023-09-27 18:10:51
此代码用于用户登录。一开始我对此很满意,但我想稍微改进一下。这些行是:
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
return selectedUser;
问题是return语句直到窗体关闭后才执行。到目前为止我还没有遇到任何问题,但是它看起来不对。我从一个表示层类调用这个方法。有什么建议吗?
public static Account selectUser(string userName, string password)
{
Account selectedUser = new Account();
if (sConnection.State == ConnectionState.Closed)
sConnection.Open();
OleDbCommand cmd = sConnection.CreateCommand();
OleDbDataReader dbReader = null;
string sql = "SELECT * FROM [Customer] WHERE ([userName]='" + userName + "' AND [Password]='" + password + "')";
cmd.CommandText = sql;
dbReader = cmd.ExecuteReader();
try
{
while (dbReader.Read())
{
if (dbReader.HasRows)
{
selectedUser.custID = (int)dbReader[0];
selectedUser.firstName = (string)dbReader[1];
selectedUser.lastName = (string)dbReader[2];
selectedUser.phoneNum = (string)dbReader[3];
selectedUser.custEmail = (string)dbReader[4];
selectedUser.userName = (string)dbReader[5];
selectedUser.password = (string)dbReader[6];
MessageBox.Show("Login successful!");
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
return selectedUser;
}
else
{
return null;
}
}
MessageBox.Show("Incorrect login");
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
return null;
}
所以我认为它是好的但是这里:
string sql = "SELECT * FROM [Customer] WHERE ([userName]='" + userName + "' AND [Password]='" + password + "')";
你要把它改成:
string sql = "SELECT * FROM [Customer] WHERE ([userName]= @username AND [Password]= @password";
cmd.CommandText = sql;
cmd.Parameters.Add("@username", userName);
cmd.Parameters.Add("@password", password);
防止SQL注入攻击。此外,你有这个:
MessageBox.Show("Login successful!");
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
return selectedUser;
在OleDbDataReader
打开时运行,我们不要这样做,它在屏幕打开时保持连接打开,这不是很好的做法。让我们稍微改变一下——因为您还需要处理那个读取器:
bool success = false;
string error = null;
using (OleDbDataReader dbReader = cmd.ExecuteReader())
{
try
{
while (dbReader.Read())
{
if (dbReader.HasRows)
{
selectedUser.custID = (int)dbReader[0];
selectedUser.firstName = (string)dbReader[1];
selectedUser.lastName = (string)dbReader[2];
selectedUser.phoneNum = (string)dbReader[3];
selectedUser.custEmail = (string)dbReader[4];
selectedUser.userName = (string)dbReader[5];
selectedUser.password = (string)dbReader[6];
success = true;
}
}
}
catch (Exception e)
{
error = e.ToString();
}
}
if (success)
{
MessageBox.Show("Login successful!");
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
return selectedUser;
}
MessageBox.Show(error);
return null;
看到这里的using
语句将确保OleDbDataReader
得到妥善处理。你真的需要构建和包装OleDbConnection
在using
里面,就像这样
实际上,这两行:
while (dbReader.Read())
{
if (dbReader.HasRows)
{
可以变成:
if (dbReader.Read())
{
...
}
最后一个注意事项,看起来你正在共享连接- sConnection
,请不要这样做,建立连接,使用它,然后摆脱它。请注意下面的using
语句:
using (SqlConnection c = new SqlConnection("connection string"))
{
c.Open();
}
这就是IDbConnection
应该如何使用-无论是SqlConnection
还是OleDbConnection
。
哦,还有一件事,如果OleDbConnection
连接到Microsoft SQL Server,请删除它并使用SqlConnection
对象。这两个类在性能和内存使用方面存在巨大差异。
编辑OP的评论…
如果你想要return
发生之前窗体关闭,然后使用Show
而不是ShowDialog
-然而,如果你要这样做,我不建议在这个方法内构建和启动该窗体,因为这个方法的内存将无法被垃圾收集,直到该窗体关闭。我建议有一个静态类,可以启动任何表单并调用它,也许像这样:
public static class FormManager
{
public static void ShowForm(Type t)
{
var f = Activator.CreateInstance(t);
((Form)f).Show();
}
}
然后你可以这样调用它:
FormManager.ShowForm(typeof(HotelSearchForm));
替换这两行:
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
如何纠正这个问题实际上取决于应用程序其余部分的布局。也许最简单的方法就是移动
HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();
行到调用.selectUser()
的地方,并使它们以.selectUser()
的返回值不为空为条件。
你也可以创建一个自定义的LoginEvent类,然后触发一个"LoginSuccess"或"LoginFail"事件,这可以被一个UI控制器类拾取,然后创建你的HotelSearchForm
。