Я создаю веб-приложение с использованием ASP .NET MVC5 и EF6.У меня взаимно-однозначное отношение, определенное следующим образом:
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, чтобы иметь возможность добавить новый адрес и связать его с существующим клиентом, что в точности и делается в этом руководстве:
https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
Мой AddressController был настроен именно так, как предлагается в учебном пособии, а также соответствующие представления.Но при доступе к странице «Создать» во время работы веб-приложения я могу написать название улицы и выбрать из выпадающего списка имя для клиента (что я и хочу, отображать имя клиента, а не идентификатор).
При нажатии на кнопку создания я получаю следующую ошибку:
Оператор 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>
}