【问题标题】:CRUD with Many to Many relationships in Entity Framework Core实体框架核心中具有多对多关系的 CRUD
【发布时间】:2020-09-24 17:25:11
【问题描述】:

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

采购订单模型:

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

编辑帖子方法:

[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.Name 而不是 Value
  • 当代码到达 foreachloop 以迭代项目时,它会抛出一个空异常。

【问题讨论】:

    标签: c# asp.net-core entity-framework-core


    【解决方案1】:

    对于新添加的子项,您只获得名称,您没有 ID。并在返回的数据中为子数据的关系表 id 获取空值。

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

    • 直接从视图中添加子行并更新模型中的 id,这样你 将始终在数据中有 id,您将不需要 face null id 问题。

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

    【讨论】:

      【解决方案2】:

      问题在于模型绑定,它基于名称属性。修改如下代码:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-06
        • 1970-01-01
        • 1970-01-01
        • 2021-02-15
        • 1970-01-01
        • 2020-01-26
        相关资源
        最近更新 更多