如何使此数据库交互工作?我一直在尝试,但它总是抛出异常

本文关键字:抛出异常 数据库 何使此 交互 互工作 我一直在 | 更新日期: 2023-09-27 18:27:57

我是一名学生。别担心,我的技能不足目前对任何专业组织都没有损害。

我现在正试图建立一个基于数据库的密码系统。还有很多元素要做,但现在我只想调用一些数据并将其插入到我的项目中。

目前我在if(dr.Read())上得到NullReferenceException

相关代码为:

       string strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=access.mdb";
    SqlConnection conn;
    SqlCommand cmd;
    SqlDataReader dr;
    DataTable dt;

        if (e.KeyCode == Keys.Enter)
        {
            e.Handled = true;
            e.SuppressKeyPress = true;
            try
            {
                conn = new SqlConnection(strConnectionString);
                cmd = new SqlCommand("select PASSWORD from regulate where NAME = @ID", conn);
                cmd.Parameters.AddWithValue("@ID", txtName.Text);
                conn.Open();
                dr = cmd.ExecuteReader();
            }
            catch
            { }
            if (dr.Read())
            {
                txtVaries.Text = dr["PASSWORD"].ToString();
            }
            conn.Close();
            if (txtVaries.Text == txtPW.Text)
            {
                tabControl1.TabPages.Remove(tabPW);
                tabControl1.TabPages.Remove(tabMain);
                tabControl1.TabPages.Insert(0, tabEdit);
            }

如何使此数据库交互工作?我一直在尝试,但它总是抛出异常

问题不在您告诉我们的行中,而是在之前,它是由您尝试使用SqlClient类连接到MS-Access数据库引起的。对于Access,您需要使用OleDb而不是SqlClient。错误被空的try-catch块隐藏。永远不要使用空的catch块,除非是在非常琐碎的情况下,可以在不影响程序工作的情况下恢复。

string strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=access.mdb";
if (e.KeyCode == Keys.Enter)
{
    e.Handled = true;
    e.SuppressKeyPress = true;
    using(OLeDbConnection = conn = new OleDbConnection(strConnectionString))
    using(OleDbCommand cmd = new SqlCommand("select [PASSWORD] from regulate where NAME = @ID", conn);
    {
            cmd.Parameters.AddWithValue("@ID", txtName.Text);
            conn.Open();
            using(OleDbDataReader dr = cmd.ExecuteReader())
            {
                 ......... read your data .....
            }
     }
 }

注意,我已经把单词PASSWORD放在方括号里,PASSWORD是Access中的一个保留关键字,当你在sql命令文本中使用它时,你需要消除它的歧义

另一个需要注意的是using语句。通过这种方式,您的连接、命令和读取器被释放,并且它们使用的资源在using块的右大括号处被释放。这也会关闭连接和读取器,以防出现异常,只需大量修改代码。

正如Damith先生在下面的评论中所指出的,可以使用ExecuteScalar而不是ExecuteReader来执行从一行只返回一列的查询。ExecuteScalar的性能更好,因为它没有构造一个OleDbDataReader对象来保持连接繁忙和打开直到关闭。它只返回请求的单个值,但您需要谨慎,因为如果查询没有找到任何与where子句匹配的用户,则返回值将为空

....
cmd.Parameters.AddWithValue("@ID", txtName.Text);
conn.Open();
object result = cmd.ExecuteScalar();
if(result != null)
    txtVaries.Text = result.ToString();
else
    MessageBox.Show("No user found!");

@Steve在SqlClient中使用OleDb连接字符串来回答您错误的可能原因。我想指出一个总体办法。不管你使用哪一个ADO提供程序,一个问题是你的空catch块是一个异常pac-man,它会吃掉任何错误而不报告或重新思考。

那么,dr.Read()的先决条件可能还没有满足,但即使连接抛出异常,您仍然可以调用dr.Red()。你可以在那一行有一个空读卡器。

让我们假设您的用户键入明文密码,然后您应该对其进行散列,并与数据库中的单向散列进行比较。

相反,代码的一般结构应该是:

try {
   using(var conn = new OleDbConnection(...)) {
      using(var command = new OleDbCommand("SELECT id, password FROM users WHERE username = ...", conn)) {
         conn.Open();
         using(var reader = command.ExecuteReader(...)) {
            if(reader.Read()) {
               var user = new User {
                  Id = reader.GetInt32(0), PasswordHash = reader.GetString(1)
               };
               if(User.SHA2Hash(loginPass) == user.PasswordHash)
                  return user;
               else
                  return null;  // or throw security exception
            }
         }
      }
   }
}
catch(Exception ex) {
   Logger.Error(ex);  // REPORT ERROR! DONT EAT IT
   throw new SecurityException("Login exception", ex);
}

重要的思想是在失败或成功时使用块来正确处理IDisposable资源。

注意,如果您编写查询,使其返回单个值,您可以简化,尽管我从未对登录代码这样做,通常我会使用reader返回带有各种字段的用户记录。如果您知道查询将返回1行/列,那么ExecuteScalar()会更好,因为ExecuteReader()会列出不必要的IDisposable资源。

Steve的建议让我找到了以下解决方案:

if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
e.SuppressKeyPress = true;
string strConnection = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=access.mdb";
     string strCommand = "SELECT PASSWORD FROM regulate where NAME=@ID";
        OleDbConnection conn = new OleDbConnection(strConnection);
        OleDbCommand com = new OleDbCommand(strCommand, conn);
        OleDbDataReader dr;
        com.Parameters.AddWithValue("@ID", txtName.Text);
conn.Open();
        dr = com.ExecuteReader();
        if (dr.Read())
        { 
            txtVaries.Text = dr["PASSWORD"].ToString();
        }
        conn.Close();
            if (txtVaries.Text == txtPW.Text)
            {
                tabControl1.TabPages.Remove(tabPW);
                tabControl1.TabPages.Remove(tabMain);
                tabControl1.TabPages.Insert(0, tabEdit);
            }
        }