正确的程序流程在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;
    }

正确的程序流程在3层设计时登录

所以我认为它是好的但是这里:

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得到妥善处理。你真的需要构建和包装OleDbConnectionusing里面,就像这样

实际上,这两行:

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