c# - ASP .NET MVC - 更新一对一数据失败
问题描述
我正在使用 ASP .NET MVC5 和 EF6 构建一个 Web 应用程序。我有一个一对一的关系,定义如下:
public class Client
{
public int ClientId { get; set; }
[Required]
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
[ForeignKey("Client")]
public int AddressId { get; set; }
[Required]
public string StreetName { get; set; }
public Client Client { get; set; }
}
地址是从属端。启用迁移并更新数据库后,将创建两个表,其中Address 表包含一个 ClientId 列,作为外键的结果。
然后我开始为这些类生成控制器和视图。
对于地址,我正在尝试修改创建/编辑方法和视图,以便能够添加新地址并将其关联到现有客户端,这正是本教程中所做的:
我的 AddressController 完全按照教程的建议以及各自的视图进行了定制。但是在运行 Web 应用程序时访问“创建”页面时,我可以编写街道名称并从下拉列表中选择客户端的名称(这是我想要的,显示客户端名称而不是 Id)。
点击创建按钮时,出现以下错误:
INSERT 语句与 FOREIGN KEY 约束“FK_dbo.Addresses_dbo.Clients_AddressId”冲突。冲突发生在数据库“myDb”、表“dbo.Clients”、列“ClientId”中。该语句已终止。
这使我相信外键 ClientId 没有像它应该通过在下拉列表中选择一个名称来更新。我尝试添加没有关联地址的新客户端,但即使选择没有关联地址的客户端,错误仍然存在。
我也知道,理想情况下,下拉列表实际上应该只显示没有任何关联地址的客户,但我不知道如何实现这一点。
因为我遵循了上述教程的每一步,所以我真的不知道我做错了什么。
任何帮助将不胜感激!如果需要发布更多代码,我会这样做,只是为了缩短这篇已经很长的帖子而没有这样做。
更新代码
地址控制器.cs
public class AddressesController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Addresses
public ActionResult Index()
{
var addresses = db.Addresses.Include(m => m.Client);
return View(addresses.ToList());
}
// GET: Addresses/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Address address = db.Addresses.Find(id);
if (address == null)
{
return HttpNotFound();
}
return View(address);
}
// GET: Address/Create
public ActionResult Create()
{
PopulateClientsDropDownList();
return View();
}
// POST: Addresses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "AddressId,StreetName,ClientId")] Address address)
{
try
{
if (ModelState.IsValid)
{
db.Addresses.Add(addresses);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException dex)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
ErrorSignal.FromCurrentContext().Raise(dex);
}
PopulateClientsDropDownList(address.ClientId);
return View(address);
}
// GET: Addresses/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Address address = db.Address.Find(id);
if (address == null)
{
return HttpNotFound();
}
PopulateClientsDropDownList(address.ClientId);
return View(address);
}
// POST: Addresses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var addressToUpdate = db.Addresses.Find(id);
if (TryUpdateModel(addressToUpdate, "",
new string[] { "StreetName", "ClientId" }))
{
try
{
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException dex)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
ErrorSignal.FromCurrentContext().Raise(dex);
}
}
PopulateAddressesDropDownList(addressToUpdate.ClientId);
return View(addressToUpdate);
}
private void PopulateClientsDropDownList(object selectedClient = null)
{
var clientsQuery = from d in db.Clients
orderby d.Name
select d;
ViewBag.ClientId = new SelectList(clientsQuery, "ClientId", "Name", selectedClient);
}
}
Create.cshtml (缩短)
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Addresses</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@*<div class="form-group">
@Html.LabelFor(model => model.AddressId, "AddressId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("AddressId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.AddressId, "", new { @class = "text-danger" })
</div>
</div>*@
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="ClientId">Client Name</label>
<div class="col-md-10">
@Html.DropDownList("ClientId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.ClientId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
解决方案
推荐阅读
- android - 修复 rt.jar 在 android studio 中找不到
- r - 在 R 中是否可以在创建数据帧的自制函数中使用输入数据帧名称?
- apache-spark - 了解 pandas_udf
- laravel - Laravel 8 分页集合 (sortBy)
- azure-active-directory - 如何在多租户守护程序应用程序上获取用户的租户 ID?
- python - 设置切比雪夫插值
- android - java.lang.IllegalArgumentException 当android意图
- xml - Powershell xml 检查值
- javascript - 有没有办法可以清空我的对象以使 new Dates() 能够插入到我的日历中?
- c++ - 关于 C++ 中运算符重载的非常简单的问题