1

此代码用于登录用户。最初我对此很满意,但我想稍微清理一下。有问题的行是:

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;
    }
4

2 回答 2

2

所以我认为没关系,但在这里:

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应该使用的方式 - 无论是 aSqlConnection还是OleDbConnection.

哦,还有一件事,如果那OleDbConnection是连接到 Microsoft SQL Server,请摆脱它并使用该SqlConnection对象。这两个类在性能和内存使用方面存在巨大差异。

编辑以供OP评论...

如果您希望在表单关闭之前return发生,请使用而不是 -但是,如果您要这样做,我不建议在此方法中构建和启动该表单,因为此方法的内存将无法被垃圾收集,直到该表单关闭。我建议有一个可以启动任何表单并调用它的静态类,可能是这样的:ShowShowDialog

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();
于 2013-04-25T20:04:05.660 回答
1

你如何纠正这个问题实际上取决于你的应用程序的其余部分是如何布局的。可能最简单的做法是移动

HotelSearchForm hotelsearchForm = new HotelSearchForm();
hotelsearchForm.ShowDialog();

行到.selectUser()被调用的任何地方,并使它们以返回值.selectUser()不为空为条件。

您还可以创建一个自定义 LoginEvent 类,然后触发“LoginSuccess”或“LoginFail”事件,该事件可由 UI 控制器类拾取,进而创建您的HotelSearchForm.

于 2013-04-25T20:00:48.430 回答