如何删除含双主键的数据库表行?MVC C#遇400错误求助
我之前也碰到过一模一样的问题!当用复合主键删除数据时,MVC的默认路由和模型绑定很容易踩坑,直接导致400 Bad Request错误。单个主键能正常工作是因为默认路由刚好匹配{id}参数,但复合主键需要传递多个值,得针对性调整代码,让我一步步帮你解决:
核心原因
HTTP 400错误本质是请求参数无法被MVC正确绑定到Controller方法,默认路由只支持单个id参数,复合主键的多个值没被正确传递或识别。
1. 先确保Model的复合主键配置正确
首先要明确标记模型的复合主键,让EF和MVC都能识别:
using System.ComponentModel.DataAnnotations; public class YourModel { // 标记第一个主键 [Key] public int PrimaryKey1 { get; set; } // 标记第二个主键 [Key] public int PrimaryKey2 { get; set; } // 其他业务属性 public string Name { get; set; } public DateTime CreateTime { get; set; } }
注意:如果用Fluent API配置EF,也要确保正确设置复合主键,比如在
DbContext的OnModelCreating里添加:modelBuilder.Entity<YourModel>() .HasKey(m => new { m.PrimaryKey1, m.PrimaryKey2 });
2. 修改Controller的Delete方法,支持多参数绑定
默认的Delete方法只接收单个id,要改成接收所有主键参数,同时调整路由匹配:
public class YourController : Controller { private YourDbContext db = new YourDbContext(); // GET: 删除确认页面,接收两个主键参数 // 路由会匹配:YourController/Delete/1/2(1是PrimaryKey1,2是PrimaryKey2) public ActionResult Delete(int primaryKey1, int primaryKey2) { var targetItem = db.YourModels.Find(primaryKey1, primaryKey2); if (targetItem == null) { return HttpNotFound(); } return View(targetItem); } // POST: 执行删除操作,同样接收两个主键参数 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public ActionResult DeleteConfirmed(int primaryKey1, int primaryKey2) { var targetItem = db.YourModels.Find(primaryKey1, primaryKey2); db.YourModels.Remove(targetItem); db.SaveChanges(); return RedirectToAction("Index"); } }
3. 调整View,确保传递所有主键值
不管是生成删除链接,还是提交删除表单,都要把两个主键值传递给Controller:
列表页的删除链接(跳转到确认页面)
@foreach (var item in Model) { <tr> <td>@item.PrimaryKey1</td> <td>@item.PrimaryKey2</td> <td>@item.Name</td> <td> @Html.ActionLink("删除", "Delete", new { primaryKey1 = item.PrimaryKey1, primaryKey2 = item.PrimaryKey2 }, new { @class = "btn btn-danger" }) </td> </tr> }
删除确认页的提交表单
要把两个主键作为隐藏字段加入表单,确保POST请求时能传递:
@model YourNamespace.YourModel @{ ViewBag.Title = "确认删除"; } <h2>确认删除这条数据?</h2> <div> <dl class="dl-horizontal"> <dt>@Html.DisplayNameFor(m => m.PrimaryKey1)</dt> <dd>@Html.DisplayFor(m => m.PrimaryKey1)</dd> <dt>@Html.DisplayNameFor(m => m.PrimaryKey2)</dt> <dd>@Html.DisplayFor(m => m.PrimaryKey2)</dd> <dt>@Html.DisplayNameFor(m => m.Name)</dt> <dd>@Html.DisplayFor(m => m.Name)</dd> </dl> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <!-- 隐藏字段传递主键 --> @Html.HiddenFor(m => m.PrimaryKey1) @Html.HiddenFor(m => m.PrimaryKey2) <button type="submit" class="btn btn-danger">确认删除</button> @Html.ActionLink("返回列表", "Index", null, new { @class = "btn btn-default" }) } </div>
额外注意点
- 如果你的路由配置有自定义规则,要确保允许传递多个参数,避免路由冲突;
- 测试时可以打开浏览器的开发者工具,查看请求的URL和FormData,确认两个主键值都被正确传递;
- 如果还是报400,检查ModelState是否有验证错误(可以在Controller里加
if (!ModelState.IsValid)判断)。
内容的提问来源于stack exchange,提问作者Luis Acuña
相关产品推荐
相关产品推荐

