【问题标题】:null value exception when entering into database进入数据库时​​出现空值异常
【发布时间】:2015-11-29 13:51:20
【问题描述】:

我在基于服务的数据库中创建了一个表来存储销售信息。该表包括列日期、时间、名称、购买、数量、成本(以这种特定方式)。插入表格的代码是

SqlConnection conn = new SqlConnection(@"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\rnawa_000\Documents\Visual Studio 2013\Projects\Random\Random\sales.mdf;Integrated Security=True");
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "insert into salesTB (Date,Time,Name,Quantity,Cost) values ('"+date.Text+"','"+time.Text+"','"+txtName.Text+"','"+listBox1.Items.Count+"','"+ txtCost.Text+")";

foreach (string item in listBox1.Items)
{
    cmd.CommandText = "insert into salesTB (Purchase) values ('" +item.Substring(0,10)  + "')";
}
cmd.ExecuteNonQuery();
cmd.Clone();
conn.Close();

date.texttime.text 标签分别显示日期和时间。它们在表单加载事件中被分配了它们的值。 txtName.texttxtCost.text 标签使用构造函数 as 从之前的表单中获取它们的值

public Form2(ListBox.ObjectCollection objectCollection, string name,string total)
{
    InitializeComponent();
    this.listBox1.Items.AddRange(objectCollection);
    txtName.Text = name;
    txtCost.Text = total;   
}

当我执行此操作时,它给了我一个错误消息“无法将值 NULL 插入到列‘成本’中”。如果我在数据库的成本列中设置了允许空值,那么它会在异常错误中显示任何其他列名。

【问题讨论】:

  • 用户可以通过文本字段将代码注入您的数据库。 绑定参数,不要连接 SQL 字符串。其次,您可能尝试将字符串 'NULL' 插入 int/decimal 字段。
  • 第一个命令文本永远不会执行,循环期间构建的命令永远不会执行,除了退出循环时的最后一个。
  • 此外,每次在初始插入后执行 foreach 循环时,您都会插入一个新行,因此第一个插入和第二组插入之间没有关系。更好的方法是保持数据标准化,并在每个项目中插入所有数据。
  • 你也不应该在你的项目中使用源数据库AttachDbFilename;这将破坏您的源项目,并且在您尝试部署应用程序时将无法正常工作。使用|DataDirectory|

标签: c# mysql sql-server


【解决方案1】:

这是一种更好、更安全的方式来做你想做的事:

      string SQLQuery = "INSERT INTO salesTB (Date,Time,Name,Quantity,Cost)" +
                            "VALUES (@date, @time, @name, @quantity, @cost)";

        using (SqlConnection DBConn = new SqlConnection(cs.ToString()))
        {
            using (SqlCommand sqlCmd = new SqlCommand(SQLQuery, DBConn))
            {
                sqlCmd.Parameters.Add("@date", SqlDbType.Text);
                sqlCmd.Parameters["@date"].Value = date.Text;

                sqlCmd.Parameters.Add("@time", SqlDbType.Text);
                sqlCmd.Parameters["@time"].Value = time.Text;

                sqlCmd.Parameters.Add("@name", SqlDbType.Text);
                sqlCmd.Parameters["@name"].Value = txtName.Text;

                sqlCmd.Parameters.Add("@quantity", SqlDbType.Int);
                sqlCmd.Parameters["@quantity"].Value = listBox1.Items.Count;

                sqlCmd.Parameters.Add("@cost", SqlDbType.Text);
                sqlCmd.Parameters["@cost"].Value = txtCost.Text

                DBConn.Open();
                sqlCmd.ExecuteNonQuery();
                DBConn.Close();
            }
        }

【讨论】:

  • 谢谢。该表包含一列“购买”,我希望所有值都出现在列表框中。你能告诉我怎么做吗?
  • INSERT INTO salesTB (Date,Time,Name,Quantity,Cost,Purchase)" "VALUES (@date, @time, @name, @quantity, @cost,@anythingyouwantPurchase) 然后sqlCmd.Parameters.Add("@anythingyouwantPurchase", SqlDbType.Text); sqlCmd.Parameters["@anythingyouwantPurchase"].Value = txtPurchase.Text;
  • 我想要列表框中的所有值。我可以使用任何列表框功能吗?
  • 将其弹出到它自己的方法中,例如:public void SaveItems(string pItem) 然后你可以使用你的 foreach 循环来执行 foreach (string item in listBox1.Items) SaveItems(item); 然后你可以在这里使用这个参数 sqlCmd.Parameters["@cost"].Value = pItem.Substring(0,10) 这可以让你插入到这个表中另一种方法
【解决方案2】:

您需要使用参数化查询来避免错误,因为您要连接显式字符串值。您的逻辑也是错误的,这样做会导致未标准化的数据,这对于任何数据库管理员来说都是可怕的排序。我会考虑改用这个:

SqlConnection conn = new SqlConnection(@"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\rnawa_000\Documents\Visual Studio 2013\Projects\Random\Random\sales.mdf;Integrated Security=True");

SqlCommand cmd = new SqlCommand();

cmd.Connection = conn;
conn.Open();

foreach (string item in listBox1.Items)
{
    cmd.CommandText = "insert into salesTB (Date,Time,Name,Quantity,Cost,Purchase) values (@date, @time, @name, @quantity, @cost, @purchase)";

    cmd.Parameters.Add(new SqlParameter("date", date.Text));
    cmd.Parameters.Add(new SqlParameter("time", time.Text));
    cmd.Parameters.Add(new SqlParameter("name", txtName.Text));
    cmd.Parameters.Add(new SqlParameter("quantity", listBox1.Items.Count));
    cmd.Parameters.Add(new SqlParameter("cost", txtCost.Text));
    cmd.Parameters.Add(new SqlParameter("purchase", item.Substring(0,10)));

    cmd.ExecuteNonQuery();
    cmd.Clone();
}

conn.Close();

它没有经过测试,但你明白了。

【讨论】:

  • 感谢您的帮助。我得到了关于使用参数化查询的想法。但是从您上面的代码中,我认为它将在表中为列表框中的每个项目添加一个新行。你能告诉我如何在购买列中获取所有 item.substring 值。
  • 也将上述内容包装在 using ;)
  • 没错。为什么你想要一行用于购买,然后另一行完全不相关,NULL 只显示购买?这不是良好的 RDBMS 做法。
  • 再一次,虽然我理解你想要什么,但我建议不要将逗号分隔的值存储在列中。更好的方法是将每个项目及其成本存储在单独的行中,然后您可以使用VIEW 编写一个查询,该查询将为您汇总。这个想法是,你越深入每个事务的每个项目越好,所以如果你以后需要返回并更改事务,你可以这样做,因为你有一个规范化的数据模型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 2018-01-30
相关资源
最近更新 更多