C#操作Access数据库时遇Data type mismatch异常无法保存数据
解决Data Type Mismatch异常的方案
核心问题分析
- OleDb参数按位置匹配而非名称匹配:你写的命名参数不会被OleDb识别,它只会按参数添加顺序对应SQL语句中
VALUES的顺序。你的参数添加顺序和SQL字段顺序不匹配,还多了一个不必要的@id参数,直接导致类型不匹配。 - 参数数量不匹配:SQL的
VALUES里只有11个占位符,但你添加了12个参数(多了@id),引发匹配错误。 - 未处理空值与类型转换:DataGridView单元格的值可能是
DBNull.Value,或类型与数据库字段不匹配(比如数字字段传了未转换的object)。
修正步骤
1. 移除多余参数,匹配参数顺序
删除cmd.Parameters.AddWithValue("@id", ...)这一行(INSERT语句无对应字段),并确保参数添加顺序严格对应SQL中VALUES的字段顺序:
SQL字段顺序:CUST_ID, FIRST_NAME, LAST_NAME, ADDRESS, CITY, STATE, POSTAL, EMAIL, BALANCE, CREDIT_LIMIT, REP_ID
2. 显式转换数据类型,处理空值
针对数据库字段类型转换参数值,空值用DBNull.Value代替,避免类型不匹配。
修正后的代码
private void button2_Click_1(object sender, EventArgs e) { string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:/Users/sdepasqu/Documents/Customer Database.accdb"; // 连接放在循环外,减少资源消耗 using (OleDbConnection conn = new OleDbConnection(connString)) { conn.Open(); // 用?作为占位符,更符合OleDb的位置匹配逻辑 using (OleDbCommand cmd = new OleDbCommand(@"INSERT INTO customer([CUST_ID], [FIRST_NAME], [LAST_NAME], [ADDRESS], [CITY], [STATE], [POSTAL], [EMAIL], [BALANCE], [CREDIT_LIMIT], [REP_ID]) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn)) { foreach (DataGridViewRow row in dataGridView1.Rows) { // 跳过DataGridView的空新行 if (row.IsNewRow) continue; cmd.Parameters.Clear(); // 按SQL字段顺序添加参数,显式处理类型和空值 cmd.Parameters.AddWithValue("", row.Cells["cUSTIDDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["fIRSTNAMEDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["lASTNAMEDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["aDDRESSDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["cITYDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["sTATEDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["pOSTALDataGridViewTextBoxColumn"].Value ?? DBNull.Value); cmd.Parameters.AddWithValue("", row.Cells["eMAILDataGridViewTextBoxColumn"].Value ?? DBNull.Value); // BALANCE:转换为decimal类型 var balanceVal = row.Cells["bALANCEDataGridViewTextBoxColumn"].Value; cmd.Parameters.AddWithValue("", balanceVal == DBNull.Value || balanceVal == null ? DBNull.Value : Convert.ToDecimal(balanceVal)); // CREDIT_LIMIT:转换为decimal类型 var creditLimitVal = row.Cells["cREDITLIMITDataGridViewTextBoxColumn"].Value; cmd.Parameters.AddWithValue("", creditLimitVal == DBNull.Value || creditLimitVal == null ? DBNull.Value : Convert.ToDecimal(creditLimitVal)); // REP_ID:转换为int类型 var repIdVal = row.Cells["rEPIDDataGridViewTextBoxColumn"].Value; cmd.Parameters.AddWithValue("", repIdVal == DBNull.Value || repIdVal == null ? DBNull.Value : Convert.ToInt32(repIdVal)); cmd.ExecuteNonQuery(); } } } }
额外说明
- 若你明确数据库字段的精确类型(比如CUST_ID是文本/数字),可以进一步精准转换(如文本用
Convert.ToString()),确保完全匹配。 - 把连接和命令放在循环外,避免重复创建销毁资源,提升执行效率。
内容的提问来源于stack exchange,提问作者Salvatore A Depasquale
相关产品推荐
相关产品推荐

