C# 需要关闭与命令关联的SqlDataReader才能成功登录

C# 需要关闭与命令关联的SqlDataReader才能成功登录,c#,database,visual-studio,sqldatareader,C#,Database,Visual Studio,Sqldatareader,每次尝试使用正确的凭据登录时,我都会收到以下错误消息: 已存在与此命令关联的打开的DataReader,必须先关闭该命令 请有人能剖析这段代码,这样我才能最终进入下一阶段,谢谢大家 // Login Function for Manual Login public void ent() { try { SqlConnection con = new SqlConnection(cc.connectDB()); con.Open();

每次尝试使用正确的凭据登录时,我都会收到以下错误消息:

已存在与此命令关联的打开的DataReader,必须先关闭该命令

请有人能剖析这段代码,这样我才能最终进入下一阶段,谢谢大家

// Login Function for Manual Login
public void ent()
{
    try
    {
        SqlConnection con = new SqlConnection(cc.connectDB());
        con.Open();
        SqlCommand cmd = new SqlCommand("delete from log", con);
        cmd.ExecuteNonQuery();
        SqlCommand cmd1 = new SqlCommand("select * from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
        cmd1.ExecuteNonQuery();
        SqlDataReader c = cmd1.ExecuteReader();
        if (c.Read() == true)
        {
            SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
            Int32 count = (Int32)cmd2.ExecuteScalar();
            if (count == 1)
            {
                SqlCommand cmd3 = new SqlCommand("insert into log values ('" + 1 + "')", con);
                cmd3.ExecuteNonQuery();
            }
            else
                if (count == 2)
                {
                    SqlCommand cmd3 = new SqlCommand("insert into log values ('" + 2 + "')", con);
                    cmd3.ExecuteNonQuery();
                }
            Menu shw = new Menu();
            shw.Show();
            this.Hide();
        }
        else
        {
            MessageBox.Show("Login failed");
        }
    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.Message);
    }
}

我正在连接一个已完全启动并运行的SQL Express服务器,但我似乎无法找到一种方法来关闭读卡器,而不会导致不必要的错误。

问题可能源于此,即您不应该调用无关的
cmd1.ExecuteNonQuery()cmd1.ExecuteReader()之前的代码>

编辑

在哪里?像这样。而且,您还需要修改您的查询。请注意,为了防止大量嵌套,您可以:

  var someMessageToShowToUser = "";
  try
  {
     using (var con = new SqlConnection(cc.connectDB()))
     using (var cmd = new SqlCommand("delete from log", con))
     using (var cmd1 = new SqlCommand(
              "select * from Login where username=@UserName and password=@Password", con))
     {
        con.Open();
        cmd.ExecuteNonQuery();
        cmd1.Parameters.AddWithValue("@UserName", username.Text);
        cmd1.Parameters.AddWithValue("@Password", password.Text);
        // cmd1.ExecuteNonQuery(); -> Delete this line.
        using (var c = cmd1.ExecuteReader())
        {
           if (c.Read() == true)
           {
              using (var cmd2 = new SqlCommand("Parameterize me too")
              {
                 var count = (Int32) cmd2.ExecuteScalar();
                 if (count == 1)
                 {
                    using (var cmd3 = new SqlCommand("insert into log values (@AnotherParam)", con))
                    {
                       cmd3.ExecuteNonQuery();
                    }
                 }
                 else if (count == 2)
                 {
                    using (var cmd3 = new SqlCommand("insert into log values (@AnotherParam)", con))
                    {
                       cmd3.ExecuteNonQuery();
                    }
                 }
                 Menu shw = new Menu();
                 shw.Show();
                 this.Hide();
              }
           }
           else
           {
              someMessageToShowToUser = "Login failed";
           }
        }
     }
 }
 catch (Exception ee)
 {
    someMessageToShowToUser = ee.Message;
 }
 MessageBox.Show(someMessageToShowToUser);

我想另一点是,在打开数据库连接时显示
消息框(等待用户单击按钮)不是一个好主意。理想情况下,您需要将数据访问代码与演示文稿代码分离(可能还需要进一步分离)。

在同一个表(dbo.LOGIN)上执行select两次,而无需在第二次执行前关闭读卡器

而不是跟随这一行

 SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
 Int32 count = (Int32)cmd2.ExecuteScalar();
您可以将typeid读取为

INT32 count = Convert.ToInt32(c["typeid"].ToString());
另外,建议您处理连接、命令和读取器对象,否则您迟早会遇到一些错误

比如说

using(SqlConnection con = new SqlConnection(cc.connectDB())
  {
    con.Open();
    using(SqlCommand cmd = new SqlCommand("delete from log", con))
      {
            cmd.ExecuteNonQuery();
      }
    using(SqlCommand cmd1 = new SqlCommand("select * from Login where username='" + username.Text + "' and password='" + password.Text + "'", con))
      {
         //You don't need this
         //cmd1.ExecuteNonQuery();
         using(SqlDataReader c = cmd1.ExecuteReader())
              {
                //You don't need these lines - this is probably the line of error
                //SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
                //Int32 count = (Int32)cmd2.ExecuteScalar();
                INT32 count = Convert.ToInt32(c["typeid"].ToString());

                //other sruffs
              }
       }
  }

使用c.Dispose();在最后一块。同意@Anurag Jain。您必须使用finally block和dispose数据读取器。感谢您的快速响应,我将在何处插入建议的代码?由于每次将“dispose”命令作为“finally”命令放置在代码中时都会出现错误,我可以用什么方式建立“dispose”命令?您可以使用block将连接对象包围起来。查看更新后的答案。如果您已在finally block中处理了对象,那么就可以了(您不需要使用block)。我使用MARS最终解决了这个问题,完成了一次完整的处理!
INT32 count = Convert.ToInt32(c["typeid"].ToString());
using(SqlConnection con = new SqlConnection(cc.connectDB())
  {
    con.Open();
    using(SqlCommand cmd = new SqlCommand("delete from log", con))
      {
            cmd.ExecuteNonQuery();
      }
    using(SqlCommand cmd1 = new SqlCommand("select * from Login where username='" + username.Text + "' and password='" + password.Text + "'", con))
      {
         //You don't need this
         //cmd1.ExecuteNonQuery();
         using(SqlDataReader c = cmd1.ExecuteReader())
              {
                //You don't need these lines - this is probably the line of error
                //SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
                //Int32 count = (Int32)cmd2.ExecuteScalar();
                INT32 count = Convert.ToInt32(c["typeid"].ToString());

                //other sruffs
              }
       }
  }