首页 > 解决方案 > C# SqlCommands 不起作用

问题描述

我有一个代码不起作用的问题,我正在尝试填充保存在 SQL Server 上 localhost 中的数据库,但代码什么也没做:(

private void button2_Click(object sender, EventArgs e)
{
    try
    {
        conn.Open();

        if (dataGridView1.SelectedRows.Count != 0 && listBox1.SelectedIndex != -1)
        {
            string id = "select studentID from student where studentName like '%" + listBox1.SelectedItem.ToString() + "%'";

            SqlCommand a = new SqlCommand(id, conn);

            a.ExecuteNonQuery();

            SqlDataReader reader = a.ExecuteReader();

            string s = reader.GetString(0);

            string q = "insert into Borrow values (" + dataGridView1.CurrentRow.Cells[0].Value.ToString()
                + ", " + s + " , '" + DateTime.Now + "' , Null)";

            SqlCommand cmd = new SqlCommand(q, conn);

            cmd.ExecuteNonQuery();
            MessageBox.Show("Book is now Borrowed");

            string tmp = "update Book set quantity=quantity-1 where bookID " + dataGridView1.CurrentRow.Cells[0].Value.ToString();
            SqlCommand tm = new SqlCommand(tmp, conn);
        }
    }
    catch
    {
    }
    finally
    {
        conn.Close();
    }
}

标签: c#asp.netsql-serverado.net

解决方案


此代码存在多个问题,不幸的是,现有(现已删除)答案都没有提及,更不用说帮助修复了。

  • marc_s 警告过 SQL 注入风险。
  • 所有这些命令都必须在一个事务中。
  • 您正在使用like获取学生 ID,但您从列表框中获取名称 - 那么为什么不将 id 作为 ListBoxItem 的值呢?
  • 在你可以借书之前,你必须首先确保你至少有一本可以借
  • 你正在吞咽异常
  • 您正在使用类级变量 for SqlConnection, whileSqlConnection最好用作 using 语句中的局部变量。
  • 您正在将代码与显示混合 - 这将是不可能的,或者至少很难测试。可测试性是可维护性的一部分。
  • 你的变量命名很糟糕。变量名应该是有意义的——这样当有人阅读代码时,他们可以通过阅读变量名来了解变量的含义。
  • 唯一应该在try块内的是实际的数据库访问。异常和Try...catch块适用于您无法在代码中测试或控制的内容。

综上所述,这里有一个稍微改进的代码版本作为起点。请尝试进一步改进它以解决我上面列出的所有(或至少大部分)问题:

private void button2_Click(object sender, EventArgs e)
{
    if (dataGridView1.SelectedRows.Count != 0 && listBox1.SelectedIndex != -1)
    {            
        using(var con = new SqlConnection(connectionString))
        {
            var trn = con.BeginTransaction();
            var sqlGetStudentId = "select studentID from student where studentName = @studentName";   
            using(var cmd = new SqlCommand(sqlGetStudentId, conn))
            {
                cmd.Parameters.Add("@studentName", SqlDbType.VarChar).Value = listBox1.SelectedItem.ToString();
                try
                {
                    con.Open();
                    string studentId = cmd.ExecuteScalar()?.ToString();

                    if(!string.IsNullOrEmpty(studentId))
                    {
                        // Note: You must first check if there are books left to borrow!
                        cmd.CommandText = "update Book set quantity=quantity-1 where bookID = @BookId";
                        cmd.Parameters.Clear();
                        cmd.Parameters.Add("@BookId", SqlDbType.VarChar).Value = dataGridView1.CurrentRow.Cells[0].Value.ToString();
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "insert into Borrow (/* Alwasy specify columns list! */) values (@IAmGuessingBookId, @StudentId, GETDATE(), NULL)";
                        cmd.Parameters.Clear();
                        cmd.Parameters.Add("@IAmGuessingBookId", SqlDbType.VarChar).Value = dataGridView1.CurrentRow.Cells[0].Value.ToString();
                        cmd.Parameters.Add("@StudentId", SqlDbType.VarChar).Value = studentId;
                        cmd.ExecuteNonQuery();

                        trn.Commit();
                    }
                }
                catch(Exception ex)
                {
                    // Do something with the exception!
                    // show an error description to the client,
                    // log for future analisys
                    trn.Rollback();
                }
            }
        }

    }
}

推荐阅读