我尝试使用带有ID的DGV行点击时填充的文本框中的值来更新记录。我已经检查了数据库并且字段是正确的,但它表示没有给出一个或多个必需参数的值。
这是我的代码:
#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
我很困惑因为insert事件执行相同的操作(从文本框中获取值并插入它们)而没有任何错误。
我错过了什么吗?
如果不清楚,我可以尝试提供更多信息
感谢帮助
谢谢!
答案 0 :(得分:1)
您正在传递各种TextBox的value属性。如果尚未使用有效Text设置这些TextBox,则value属性将为null。这是一个.Net null,它与数据库null不同。要传递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);
}
}
编辑
为了将更新语句限制为仅具有TextBoxes的字段,您需要动态构建Update语句。这些方面应该有用:
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已经是一个字符串了。
我认为这些更改应该足以使其正常工作,但如果不是,请告诉我!我故意试图将更改保持在最低限度,以便代码最接近您自己的代码。这并不意味着,我自己会这样编码;我相信不会让初学者感到窒息。使用大量的红色墨水!