#c# #asp.net-core #entity-framework-core
#c# #asp.net-core #entity-framework-core
Вопрос:
У меня есть две модели и одна таблица соединений. Я хотел бы использовать тот же вид для редактирования и создания нового заказа на покупку при добавлении товаров в той же форме.
Модель PurchaseOrder:
public class PurchaseOrder
{
public int ID { get; set; }
[Required]
public string Requester { get; set; }
public int WorkOrder { get; set; }
[Required]
public string WorkSite { get; set; }
public string Equipment { get; set; }
public string Operator { get; set; }
public string Remarks { get; set; }
public ICollection<PurchaseOrderItem> Items { get; set; }
}
Модель элемента:
public class Item
{
public int ID { get; set; }
public string PartNumber { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
public int Quantity { get; set; }
public string Remarks { get; set; }
public ICollection<PurchaseOrderItem> PurchaseOrders { get; set; }
}
Присоединиться к объекту таблицы
public class PurchaseOrderItem
{
public int PurchaseOrderID { get; set; }
public int ItemID { get; set; }
public PurchaseOrder PurchaseOrder { get; set; }
public Item Item { get; set; }
}
PurchaseOrdersController Редактировать:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var purchaseOrder = await _context.PurchaseOrders
.Include(x => x.Items)
.ThenInclude(x => x.Item)
.Where(x => x.ID == id)
.AsNoTracking()
.SingleOrDefaultAsync();
if (purchaseOrder == null)
{
return NotFound();
}
return View(purchaseOrder);
}
Редактировать метод Post:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, PurchaseOrder order)
{
if (id != order.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
var po = _context.PurchaseOrders.FirstOrDefault(i => i.ID == order.ID);
po.Requester = order.Requester;
po.WorkOrder = order.WorkOrder;
po.WorkSite = order.WorkSite;
po.Equipment = order.Equipment;
po.Operator = order.Operator;
po.Remarks = order.Remarks;
_context.Update(po);
foreach (var i in order.Items)
{
var item = _context.Items.FirstOrDefault(n => n.ID == i.Item.ID);
item.PartNumber = i.Item.PartNumber;
item.Name = i.Item.Name;
item.Description = i.Item.Description;
item.Quantity = i.Item.Quantity;
item.Remarks = i.Item.Remarks;
_context.Update(item);
}
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PurchaseOrderExists(order.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(order);
}
Редактировать представление
@model OrderTrackingApp.Models.PurchaseOrder
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>PurchaseOrder</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ID" />
<div class="form-group">
<label asp-for="Requester" class="control-label"></label>
<input asp-for="Requester" class="form-control" />
<span asp-validation-for="Requester" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="WorkOrder" class="control-label"></label>
<input asp-for="WorkOrder" class="form-control" />
<span asp-validation-for="WorkOrder" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="WorkSite" class="control-label"></label>
<input asp-for="WorkSite" class="form-control" />
<span asp-validation-for="WorkSite" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Equipment" class="control-label"></label>
<input asp-for="Equipment" class="form-control" />
<span asp-validation-for="Equipment" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Operator" class="control-label"></label>
<input asp-for="Operator" class="form-control" />
<span asp-validation-for="Operator" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Remarks" class="control-label"></label>
<input asp-for="Remarks" class="form-control" />
<span asp-validation-for="Remarks" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">Order Items</label>
<table>
<tbody>
@{ int i = 0;}
<tr>
@foreach (var OrderItem in Model.Items)
{
<td>
<input type="hidden" value="OrderItem[@i].ItemID" asp-for="@OrderItem.ItemID"
class="form-control" />
<input type="text" value="OrderItem[@i].Item.PartNumber" asp-for="@OrderItem.Item.PartNumber" class="form-control" />
<input type="text" value="OrderItem[@i].Item.Name" asp-for="@OrderItem.Item.Name" />
</td>
i ;
}
</tr>
</tbody>
</table>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
В настоящее время у меня две проблемы с редактированием:
- Метка для элемента заполняется следующим образом: OrderItem[0].Item.Имя вместо значения
- Когда код достигает foreachloop для перебора элементов, он выдает исключение null.
Ответ №1:
Вы получаете имя только для недавно добавленных дочерних элементов, у вас нет идентификаторов. и получение нулевых значений, как в возвращаемых данных для идентификаторов реляционных таблиц дочерних данных, не инициализируется.
вы можете решить эту проблему несколькими способами в соответствии с пригодностью:
-
Добавляйте дочерние строки непосредственно из представления и обновляйте идентификаторы в модели, поэтому у вас всегда будут идентификаторы в данных, и вам не нужно будет сталкиваться с проблемой нулевых идентификаторов.
-
В качестве альтернативы, вам может потребоваться сначала добавить новые значения дочерней таблицы, а затем использовать новые идентификаторы в реляционных данных вручную перед сохранением изменений.
Ответ №2:
Проблема заключается в привязке модели, она основана на атрибуте name. Измените код, как показано ниже:
@{ int i = 0;}
<tr>
@foreach (var OrderItem in Model.Items)
{
<td>
<input type="hidden" name="Items[@i].Item.ID" asp-for="@OrderItem.Item.ID"
class="form-control" />
<input type="text" name="Items[@i].Item.PartNumber" asp-for="@OrderItem.Item.PartNumber" class="form-control" />
<input type="text" name="Items[@i].Item.Name" asp-for="@OrderItem.Item.Name" class="form-control" />
</td>
i ;
}
</tr>