【问题标题】:OleDb Exception: no value given for one or more required parameters update queryOleDb 异常:没有为一个或多个必需参数更新查询提供值
【发布时间】:2017-09-05 19:29:26
【问题描述】:

我正在尝试使用文本框中的值更新一条记录,该值是在从 DGV 使用 id 进行行单击时填充的。我检查了数据库并且字段是正确的,但它说没有为一个或多个必需参数提供值。

这是我的代码:

#region adds update control to the form
    public void AddUpdateControl()
    {
        // update and delete controls
        Button updateFieldsButton = new Button()
        {
            Name = "btn_updateFields",

            Text = "Update"
        };

        updateFieldsButton.Font = new Font(updateFieldsButton.Font.FontFamily, 12);

        updateFieldsButton.Location = new Point(78, 648);

        updateFieldsButton.Size = new Size(120, 30);

        updateFieldsButton.Click += (sender, args) =>
        {
            if (MessageBox.Show("Are you sure you want to update this record?", "Update", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                UpdateData(this);
            }
        };

        Controls.Add(updateFieldsButton);
    }
    #endregion

#region shows data grid view for update
    public void ShowDataGridViewForUpdate()
    {
        qbcDataGridView.Show();

        qbcDataGridView.Font = new Font(qbcDataGridView.Font.FontFamily, 10);

        qbcDataGridView.Location = new Point(80, 100);

        qbcDataGridView.Size = new Size(1500, 500);


        DataTable dt = new DataTable();


        DbAdapter = new OleDbDataAdapter("select ID, household_head AS head, birthday, phone, email, address, status, " +
            "spouse, spouse_birthday AS sbirthday, spouse_email AS semail, anniversary, spouse_status AS sstatus, " +
            "child1, child1_birthday AS birthday1, child1_email AS email1, " +
            "child2, child2_birthday AS birthday2, child2_email AS email2, " +
            "child3, child3_birthday AS birthday3, child3_email AS email3, " +
            "child4, child4_birthday AS birthday4, child4_email AS email4, " +
            "child5, child5_birthday AS birthday5, child5_email AS email5, " +
            "child6, child6_birthday AS birthday6, child6_email AS email6, " +
            "child7, child7_birthday AS birthday7, child7_email AS email7 from members", dbc);

        DbAdapter.Fill(dt);

        if (dt != null && dt.Rows.Count > 0)
        {
            if (dt.Columns.Count > 0)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {
                    if (dt.AsEnumerable().All(row => row[i] == null || row[i].ToString() == ""))
                    {
                        dt.Columns.RemoveAt(i);
                    }
                }

                qbcDataGridView.DataSource = dt;


                qbcDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

                qbcDataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

                qbcDataGridView.DefaultCellStyle.WrapMode = DataGridViewTriState.True;


                Controls.Add(qbcDataGridView);



                qbcDataGridView.RowHeaderMouseClick += (object sender, DataGridViewCellMouseEventArgs e) =>
                {
                    id = Convert.ToInt32(qbcDataGridView.Rows[e.RowIndex].Cells[0].Value.ToString());

                    // get all the columns and assign them to textboxes text
                    for (int i = 1; i < qbcDataGridView.Rows[e.RowIndex].Cells.Count; i++)
                    {
                         // enable how many textboxes were found based on the dgv 
                         var textBox = new TextBox
                         {
                             Name = qbcDataGridView.Rows[e.RowIndex].Cells[i].Value.ToString(),

                             Font = new Font(qbcDataGridView.Font.FontFamily, 12),

                             Text = qbcDataGridView.Rows[e.RowIndex].Cells[i].Value.ToString(),

                             Location = new Point(80 + (i * 140), 50)
                         };


                         Controls.Add(textBox);
                    }
                }; 
            }
        }
        else
        {
            HideAllControls(this);

            MessageBox.Show("No records exist", "Records Error", MessageBoxButtons.OK);
        }

        dbc.Close();
    }
    #endregion


    #region updates records in the database
    public void UpdateData(Control ctrl)
    {
        try
        {
            foreach (Control c in Controls)
            {
                if (c is TextBox)
                {
                    if (!string.IsNullOrEmpty(((TextBox)c).Text))
                    {
                        updatedTextboxes.Add(new KeyValuePair<string, string>(((TextBox)c).Name, ((TextBox)c).Text));
                    }
                }
            }

            using (dbc)
            {
                dbc.Open();

                dbCmd = new OleDbCommand("UPDATE members SET household_head = ?, birthday = ?, phone = ?, " +
                    "email = ?, address = ?, status = ?, spouse = ?, spouse_birthday = ?, " +
                    "spouse_phone = ?, spouse_email = ?, anniversary = ?, spouse_status = ?, " +
                    "child1 = ?, child1_birthday = ?, child1_email = ?, " +
                    "child2 = ?, child2_birthday = ?, child2_email = ?, " +
                    "child3 = ?, child3_birthday = ?, child3_email = ?, " +
                    "child4 = ?, child4_birthday = ?, child4_email = ?, " +
                    "child5 = ?, child5_birthday = ?, child5_email = ?, " +
                    "child6 = ?, child6_birthday = ?, child6_email = ?, " +
                    "child7 = ?, child7_birthday = ?, child7_email = ? WHERE ID = " + id, dbc);


                for (int i = 0; i < updatedTextboxes.Count; i++)
                {
                    dbCmd.Parameters.AddWithValue(updatedTextboxes[i].Key.ToString(), updatedTextboxes[i].Value);
                }

                if (dbCmd.ExecuteNonQuery() > 0) // RAWR not updating.. wrong parameter value.. check query
                {
                    MessageBox.Show("Record updated", "QBC", MessageBoxButtons.OK);

                    ClearAll(ctrl);
                }
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        dbc.Close();
    }
    #endregion

异常截图-https://imgur.com/6pstqOH

应用截图 - https://imgur.com/CTGZgeG

数据库截图(访问)-https://imgur.com/UkEjxdm

我很困惑,因为插入事件做了同样的事情(从文本框中获取值并插入它们)而没有任何错误。

我错过了什么吗?

如果不清楚,我可以尝试提供更多信息

感谢帮助

谢谢!

【问题讨论】:

  • 我只能说你的 UPDATE 语句有一个 spouse_phone 字段,而你的 SELECT 语句中没有这个字段。
  • 我看到 from 上只有 6 个文本框,而更新查询有 6 个以上的参数。您是否调试过代码并检查updatedTextboxes 字典中有多少项?
  • 它可以接受空值。
  • @Steve 不幸的是这不起作用:(
  • @ChetanRanpariya 我得到 6 个值。

标签: c# ms-access


【解决方案1】:

您正在传递各种文本框的 value 属性。如果这些文本框没有设置有效的文本,则 value 属性将为 null。这是一个 .Net 空值,它与数据库空值不同。要传递 db null,您必须将参数值设置为 DBNull.Value,否则您会得到您所看到的错误消息,即缺少参数错误。为避免这种情况,请将您的 for 循环更改为:

for (int i = 0; i < updatedTextboxes.Count; i++)
{
    if (updatedTextboxes[i].Value == null)
    {
        dbCmd.Parameters.AddWithValue(updatedTextboxes[i].Key, DBNull.Value);
    }
    else
    {
        dbCmd.Parameters.AddWithValue(updatedTextboxes[i].Key, updatedTextboxes[i].Value);
    }
}

编辑

为了将您的更新语句限制在您拥有文本框的那些字段中,您需要动态构建您的更新语句。这些方面的东西应该可以工作:

dbc.Open();
dbCmd = new OleDbCommand();
var sB = new StringBuilder("UPDATE members SET ");

for (int i = 0; i < updatedTextboxes.Count; i++)
{
    if (i == 0)
    {
        sB.Append(updatedTextboxes[i].Key + " = ?");
    }
    else
    {
        sB.Append(", " + updatedTextboxes[i].Key + " = ?");
    }
    if (updatedTextboxes[i].Value == null)
    {
        dbCmd.Parameters.AddWithValue(updatedTextboxes[i].Key, DBNull.Value);
    }
    else
    {
        dbCmd.Parameters.AddWithValue(updatedTextboxes[i].Key, updatedTextboxes[i].Value);
    }
}

sB.Append(" WHERE ID = " + id);
dbCmd.CommandText = sB.ToString();

dbCmd.Connection = dbc;

if (dbCmd.ExecuteNonQuery() > 0) .....

请注意,我没有测试过这段代码!此外,为了使其正常工作,您必须将 TextBoxes 的 Name 值更改为数据的字段名称。你可以这样做:

var textBox = new TextBox
{
    Name = qbcDataGridView.Columns[i].DataPropertyName,  ...

还要注意,您不需要 Key.ToString()。你有字符串的KeyValuePairs,字符串,所以Key已经是一个字符串了。

我认为这些更改应该足以让它工作,但如果没有,请告诉我!我特意尝试将更改保持在最低限度,以便代码与您自己的代码最相似。这并不意味着我自己会这样编码;我坚信不要用大量的红墨水来扼杀初学者的工作!

【讨论】:

  • 文本框确实有值,它们是在点击时从 DGV 加载的。
  • 文本框的数量是否与参数的数量相匹配?你的屏幕截图显示的少得多。
  • 它只有 6 个,但它可以根据 dgv 是否超过 6 列而改变。我可以插入 20 或 1,它只会显示数据库中非空的列。
  • 但据我统计,您的更新有 32 个参数!您需要为所有这些提供值(或 dbnull.value)
  • 我明白这一点,但如果不手动分配所有 32 个参数,我不知道该怎么做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多