React中批量删除数据库Id列表失败问题求助
问题分析与解决方案
核心报错原因
前端执行res.json()时,后端返回的不是合法JSON(实际是SQL或ASP.NET的错误信息,开头为"Microsoft."),导致JSON解析失败。根源在于前后端参数传递、SQL执行逻辑两处存在问题。
前端代码修复
当前端传递int数组时,直接拼在URL路径里无法被后端正确解析为int[],建议改用查询参数传递数组:
deleteIdList() { const idList = this.state.selectedEmployeeIdList; if (window.confirm('确定要删除选中的员工吗?')) { // 把数组转成逗号分隔的字符串,作为查询参数 const ids = idList.join(','); fetch(`${variables.API_URL}employee?ids=${ids}`, { method : 'DELETE', headers : { 'Accept' : 'application/json', 'Content-Type' : 'application/json' } }) .then(res => { // 先检查响应是否成功,再解析JSON if (!res.ok) throw new Error(res.statusText); return res.json(); }) .then((result) => { alert('删除成功'); console.log(result); this.refreshList(); },(error)=>{ alert('无法删除选中员工! ' + error.message); }) } }
后端代码修复
1. 修正路由与参数绑定
修改HttpDelete路由,改为从查询参数接收ids数组:
[HttpDelete] public JsonResult Delete([FromQuery] int[] ids) { // 后续逻辑使用ids参数 // ... }
2. 修正SQL执行逻辑
- DELETE语句不需要用
ExecuteReader(),改用ExecuteNonQuery()获取受影响行数 - SQL Server不直接支持int[]作为IN参数,推荐使用表值参数(安全无注入风险):
步骤1:先在SQL Server创建表值类型
CREATE TYPE dbo.IntList AS TABLE (Id INT);
步骤2:修改后端代码
[HttpDelete] public IActionResult Delete([FromQuery] int[] ids) { try { if (ids == null || ids.Length == 0) return Json(new { success = false, message = "未提供员工ID" }); string query = @"DELETE FROM DBO.EMPLOYEE WHERE EMPLOYEEID IN (SELECT Id FROM @EMPLOYEEIDs)"; int affectedRows = 0; string sqlDataSource = _configuration.GetConnectionString("EmployeeAppConn"); using (SqlConnection myConn = new SqlConnection(sqlDataSource)) { myConn.Open(); using (SqlCommand cm = new SqlCommand(query, myConn)) { // 创建表值参数 DataTable tvp = new DataTable(); tvp.Columns.Add("Id", typeof(int)); foreach (int id in ids) { tvp.Rows.Add(id); } cm.Parameters.AddWithValue("@EMPLOYEEIDs", tvp); cm.Parameters["@EMPLOYEEIDs"].SqlDbType = SqlDbType.Structured; cm.Parameters["@EMPLOYEEIDs"].TypeName = "dbo.IntList"; // 执行DELETE,获取受影响行数 affectedRows = cm.ExecuteNonQuery(); } } return Json(new { success = true, message = $"成功删除 {affectedRows} 名员工!ID列表:{string.Join(", ", ids)}" }); } catch (Exception ex) { // 返回JSON格式错误,避免前端解析失败 return BadRequest(new { success = false, error = ex.Message }); } }
3. 快速测试替代方案(不推荐生产环境)
如果不想创建表值类型,可临时用字符串拆分方式(注意SQL注入风险):
[HttpDelete] public IActionResult Delete([FromQuery] string ids) { try { if (string.IsNullOrEmpty(ids)) return Json(new { success = false, message = "未提供员工ID" }); int[] idArray = ids.Split(',').Select(int.Parse).ToArray(); string query = $"DELETE FROM DBO.EMPLOYEE WHERE EMPLOYEEID IN ({ids})"; int affectedRows = 0; string sqlDataSource = _configuration.GetConnectionString("EmployeeAppConn"); using (SqlConnection myConn = new SqlConnection(sqlDataSource)) { myConn.Open(); using (SqlCommand cm = new SqlCommand(query, myConn)) { affectedRows = cm.ExecuteNonQuery(); } } return Json(new { success = true, message = $"成功删除 {affectedRows} 名员工!ID列表:{ids}" }); } catch (Exception ex) { return BadRequest(new { success = false, error = ex.Message }); } }
关键注意点
- 前端必须先检查响应状态码(
res.ok),再解析JSON,避免后端返回错误时强行解析非JSON内容。 - 后端执行DELETE、UPDATE等无返回结果的SQL语句时,必须用
ExecuteNonQuery(),不能用ExecuteReader(),否则会抛出异常。 - 传递数组参数到SQL的IN子句时,优先使用表值参数,杜绝SQL注入风险。
内容的提问来源于stack exchange,提问作者Renee Liew
相关产品推荐
相关产品推荐

