ASP.NET MVC 中一对多关系 ViewModel 的 CRUD 操作

CRUD Operation for one to many relationship ViewModel in ASP.NET MVC

这几天一直在网上找,还是没找到我想要的。也许是我的研究方式是错误的。但问题是 我有一个订单模型

public class Order
    {
        [Key]
        public int Id { get; set; }

        public int TotalItems { get; set; }

        public DateTime DeliveryDate { get; set; }

        public string OrderNumber { get; set; }
        public string DeliveryAddress { get; set; }

        [ForeignKey("ClientId")]
        public int ClientId { get; set; }
        

        public int OrderItemId { get; set; }
        [ForeignKey("OrderItemId")]

        public List<OrderItem> OrderItems { get; set; }
        public Client Client { get; set; }
    }

还有一个 OrderItem 模型

public class OrderItem
    {
        public int Id { get; set; }

        [ForeignKey("OrderId")]
        public int OrderId{ get; set; }

        public int InventoryInfoId { get; set; }
        [ForeignKey("InventoryInfoId")]

        [Required]
        public string ItemCode { get; set; }

        public int Quantity { get; set; }
        public virtual InventoryInfo InventoryInfo { get; set; }
        public Order Order { get; set; }
    }

根据用户输入,一个订单可以有多个订单项。 这是我的 OrderViewModel

public class OrderViewModel
    {
        //public int OrderId { get; set; }
        //public string OrderNumber { get; set; }
        //public string DeliveryAddress { get; set; }
        //public int ClientId { get; set; }
        //public DateTime Deliverydate { get; set; }
        public Order Order { get; set; }
        public IList<OrderItem> OrderItems { get; set; }
        public int ItemCode { get; set; }
        public int Quantity { get; set; }
    }

这是我的 Create.cshtml

<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Order.ClientId" class="control-label"></label>
                <select asp-for="Order.ClientId" class="form-control" asp-items="ViewBag.ClientId">
                    <option>-- Select Client --</option>
                </select>
                <span asp-validation-for="Order.ClientId" class="text-danger"></span>

            </div>
            <div class="form-group">
                <label asp-for="Order.OrderNumber" class="control-label"></label>
                <input asp-for="Order.OrderNumber" class="form-control" />
                <span asp-validation-for="Order.OrderNumber" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Order.DeliveryDate" class="control-label"></label>
                <input type="date" data-val="true" asp-for="Order.DeliveryDate" class="form-control" />
                <span asp-validation-for="Order.DeliveryDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Order.DeliveryAddress" class="control-label"></label>
                <input asp-for="Order.DeliveryAddress" class="form-control" />
                <span asp-validation-for="Order.DeliveryAddress" class="text-danger"></span>
            </div>

            <table id="tblCustomers" class="table" cellpadding="0" cellspacing="0">
                <thead>
                    <tr>
                        <th style="width:150px">Item Code</th>
                        <th style="width:150px">Quantity</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody></tbody>
                <tfoot id="item-list">
                    <tr>
                        <td>
                            <select asp-for="OrderItems[0].ItemCode" class="items" asp-items="@ViewBag.Item"></select>
                        </td>
                        <td><input type="text" asp-for="OrderItems[0].Quantity" class="items" /></td>
                        @*<td><input type="button" id="btnAdd" value="Add" /></td>*@
                    </tr>
                </tfoot>
            </table>
            <button id="add">Add another item</button>

            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>

        </form>
    </div>

</div>



@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script>
        $("#add").click(function (e) {
           e.preventDefault();
           var i = ($(".items").length) / 2;
           var model = @Html.Raw(@ViewBag.Items);
            var n = '<tr><td><select id="OrderItems_' + 1 + '_ItemCode" name="OrderItems[' + 1 + '].ItemCode" class="items" /></td>' +
            '<td><input type="text" class="items" name="OrderItems[' + 1 + '].Quantity" /></td></tr>'

           $("#item-list").append(n);

           var Items = "";
           $(model).each(function (e) {
               Items = Items + '<option value="' + this.Value + '">' + this.Text + '</option>'
           });

           var subItemList = $("#OrderItems" + 1 + "_ItemCode");
            subItemList.empty();
            subItemList.append(Items);
    });
    </script>

}

用户有两部分,订单详细信息和订单项目 这是我的 OrdersController Create

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("ClientId", "OrderNumber", "DeliveryDate", "DeliveryAddress")]OrderViewModel OrderVM)
        {

            try
            {
                if (ModelState.IsValid)
                {
                    var order = new Order()
                    {
                        Id = OrderVM.OrderId,
                        DeliveryAddress = OrderVM.DeliveryAddress,
                        DeliveryDate = OrderVM.Deliverydate,
                        OrderNumber = OrderVM.OrderNumber
                    };
                    _context.Add(order);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
            }
            catch (DbUpdateException ex)
            {
                //Log the error(uncomment ex variable name and write a log.
                ModelState.AddModelError("", "Unable to save changes. " +
                    "Try again, and if the problem persists " +
                    "see your system administrator.");
            }
            PopulateClientDropDownList(OrderVM.ClientId);
            CreateMultipleOrderItem();
            return View(OrderVM);
        }

我现在真的很迷茫,因为我已经尝试了几个教程并浏览了示例,但似乎没有什么可以帮助我解决这个问题。也许我无法理解他们。请大家帮帮我!

在 Jeffery 的帮助下。

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(OrderViewModel OrderVM)
        {

            try
            {
                if (ModelState.IsValid)
                {
                    //var order = new Order()
                    //{
                    //    Id = OrderVM.OrderId,
                    //    DeliveryAddress = OrderVM.DeliveryAddress,
                    //    DeliveryDate = OrderVM.Deliverydate,
                    //    OrderNumber = OrderVM.OrderNumber
                    //};
                    _context.AddRange(OrderVM);
                    
                    //_context.AddRange(OrderVM.OrderItems);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
            }
            catch (DbUpdateException ex)
            {
                //Log the error(uncomment ex variable name and write a log.
                ModelState.AddModelError("", "Unable to save changes. " +
                    "Try again, and if the problem persists " +
                    "see your system administrator.");
            }
            PopulateClientDropDownList(OrderVM.Order.ClientId);
            CreateMultipleOrderItem();
            return View(OrderVM);
        }

控制器的编辑版本允许数据从我的视图页面传递到控制器。但是有一个 error.InvalidOperationException:找不到实体类型 'OrderViewModel'。确保实体类型已添加到模型中。 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetOrCreateEntry(对象实体)


尝试这样的事情

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(OrderViewModel OrderVM)
    {

        try
        {
            if (ModelState.IsValid)
            {
                var order = new Order()
                {
                    // Id = OrderVM.OrderId,- Primary keys will be auto generated
                    DeliveryAddress = OrderVM.DeliveryAddress,
                    DeliveryDate = OrderVM.Deliverydate,
                    OrderNumber = OrderVM.OrderNumber,
                    ClientId = OrderVM.ClientId,
                    TotalItems = OrderVM.TotalItems,
                    OrderItems = OrderVM.Select(item => new OrderItem()
                    {
                     ItemCode = item.ItemCode,
                     Quantity = item.Quantity,
                     InventoryInfoId = item.InventoryInfoId
      
                    }).ToList()
                };
                await _context.Orders.AddAsync(order);
                
                //_context.AddRange(OrderVM.OrderItems);
                await _context.SaveChangesAsync();

                return RedirectToAction(nameof(Index));
            }
        }
        catch (DbUpdateException ex)
        {
            //Log the error(uncomment ex variable name and write a log.
            ModelState.AddModelError("", "Unable to save changes. " +
                "Try again, and if the problem persists " +
                "see your system administrator.");
        }
        PopulateClientDropDownList(OrderVM.Order.ClientId);
        CreateMultipleOrderItem();
        return View(OrderVM);
    }