C# 实体框架核心中具有多对多关系的CRUD

C# 实体框架核心中具有多对多关系的CRUD,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我有两个模型和一个联接表。 我想使用相同的视图编辑和创建新的采购订单,同时添加相同表单中的项目 采购订单型号: public class PurchaseOrder { public int ID { get; set; } [Required] public string Requester { get; set; } public int WorkOrder { get; set; } [Required] public string W

我有两个模型和一个联接表。 我想使用相同的视图编辑和创建新的采购订单,同时添加相同表单中的项目

采购订单型号:

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; }
}
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);
        }
公共异步任务编辑(int?id)
{
if(id==null)
{
返回NotFound();
}
var purchaseOrder=wait_context.PurchaseOrders
.包括(x=>x.Items)
.然后包括(x=>x.Item)
.其中(x=>x.ID==ID)
.AsNoTracking()
.SingleOrDefaultAsync();
if(purchaseOrder==null)
{
返回NotFound();
}
退货视图(采购订单);
}
编辑帖子方法:

[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);

        }
[HttpPost]
[ValidateAntiForgeryToken]
公共异步任务编辑(int-id,PurchaseOrder)
{
if(id!=order.id)
{
返回NotFound();
}
if(ModelState.IsValid)
{
尝试
{
var po=_context.PurchaseOrders.FirstOrDefault(i=>i.ID==order.ID);
采购订单请求者=订单请求者;
po.WorkOrder=order.WorkOrder;
po.WorkSite=订单.WorkSite;
采购订单设备=订单设备;
采购订单操作员=订单操作员;
订单备注=订单备注;
_上下文更新(po);
foreach(订单项目中的变量i)
{
var item=\u 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;
项目备注=i.项目备注;
_背景。更新(项目);
}
wait_context.SaveChangesAsync();
}
catch(DbUpdateConcurrencyException)
{
如果(!PurchaseOrderExists(order.ID))
{
返回NotFound();
}
其他的
{
投掷;
}
}
返回重定向到操作(名称(索引));
}
返回视图(订单);
}
编辑视图

@model OrderTrackingApp.Models.PurchaseOrder
@{
ViewData[“标题”]=“编辑”;
}
编辑
采购订单

订购项目 @{int i=0;} @foreach(Model.Items中的var OrderItem) { i++; } 返回列表 @节脚本{ @{wait Html.RenderPartialAsync(“_validationScript”);}
}
您只获得名称,因为对于新添加的子项,您没有ID。对于子数据的关系表ID,获取返回数据中的空值是不初始化的

根据适用性,您可以通过两种方式解决此问题:

  • 直接从视图中添加子行并更新模型中的ID,以便 将始终在数据中具有ID,并且不需要面空ID 问题

  • 或者,您可能需要首先添加子表的新值 然后在保存更改之前,在关系数据中手动使用新ID


问题在于模型绑定,它基于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>
@{int i=0;}
@foreach(Model.Items中的var OrderItem)
{
i++;
}
[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);

        }
@{ 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>