我正在使用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; }
}
其中地址是从属端。 启用迁移并更新数据库后,将创建两个表,其中,由于外键,地址表包含ClientId列。
然后我继续为这些类生成控制器和视图。
对于地址,我正在尝试修改Create / Edit方法和视图,以便能够添加新地址并将其与现有客户端相关联,这正是本教程中要做的:
我的AddressController完全按照教程的建议以及相应的视图进行了自定义。但是在运行Web应用程序时访问“创建”页面时,我可以写出街道名称,并从下拉列表中选择客户端的名称(这是我想要的,显示客户端名称而不是ID)。
点击创建按钮时,出现以下错误:
INSERT语句与FOREIGN KEY约束冲突 “ FK_dbo.Addresses_dbo.Clients_AddressId”。发生冲突 数据库“ myDb”,表“ dbo.Clients”,列“ ClientId”。该声明已经 终止。
这使我相信外键ClientId并未得到更新,因为应该通过在下拉列表中选择一个名称来进行更新。我尝试添加没有关联地址的新客户端,但是即使选择了没有关联地址的客户端,错误仍然存在。
我也知道,理想情况下,下拉列表实际上应该只显示没有任何与之相关联的地址的客户,但我不知道该怎么做。
因为我按照提到的教程的每个步骤进行操作,所以我真的不知道自己在做什么错。
任何帮助将不胜感激!如果需要发布更多代码,我会这样做,只是为了缩短本已很长的帖子而没有这样做。
AddressesController.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>
}