.Net Core 3.1 EF一对多关系同时插入主从表数据报错解决方案
错误原因
Create.cshtml.cs中的InvoiceLine属性未添加[BindProperty]特性,表单提交时Razor Pages不会将表单中的明细数据绑定到该属性,导致InvoiceLine为null,调用_context.InvoiceLine.Add()时触发空参数异常。- 一对多关联场景下没有利用EF Core的导航属性自动维护外键的能力,手动单独添加明细实体的写法更容易出错。
- 原
ApplicationDbContext的构造函数语法存在缺失,缺少方法体大括号会导致编译错误。
修复方案
1. 修改 Create.cshtml.cs
推荐直接使用 InvoiceHeader 自带的 InvoiceLines 导航属性做绑定,无需单独声明 InvoiceLine 属性,天然支持多条明细场景,EF Core会自动维护主从表外键关联:
using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using PRArchivalSystem.Model; namespace PRArchivalSystem.Pages.InvH { public class CreateModel : PageModel { private readonly ApplicationDbContext _context; public CreateModel(ApplicationDbContext context) { _context = context; } public IActionResult OnGet() { // 初始化导航属性集合,避免空引用 InvoiceHeader = new InvoiceHeader { InvoiceLines = new List<InvoiceLine>() }; return Page(); } [BindProperty] public InvoiceHeader InvoiceHeader { get; set; } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } // 仅需添加主表实体,EF Core会自动插入关联的从表明细并赋值外键 _context.InvoiceHeader.Add(InvoiceHeader); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); } } }
2. 修改 Create.cshtml 字段绑定路径
将明细字段的绑定路径调整为 InvoiceHeader.InvoiceLines[索引].属性名 格式,示例为单条明细的写法,如果需要支持多条明细,只需要用JS动态生成索引为1、2、3的输入组即可,无需修改后端代码:
@page @model PRArchivalSystem.Pages.InvH.CreateModel <h4>InvoiceHeader</h4> <hr /> <div class="row"> <div class="col-md-4"> <form method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <!-- 主表字段保持不变 --> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceNumber" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceNumber" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceNumber" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceDate" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceDate" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceDate" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceVendor" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceVendor" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceVendor" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceTotal" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceTotal" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceTotal" class="text-danger"></span> </div> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <!-- 明细字段修改绑定路径 --> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceLines[0].LineDescription" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceLines[0].LineDescription" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceLines[0].LineDescription" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceLines[0].LineAmount" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceLines[0].LineAmount" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceLines[0].LineAmount" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceLines[0].LineQuantity" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceLines[0].LineQuantity" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceLines[0].LineQuantity" class="text-danger"></span> </div> <div class="form-group form-check"> <label class="form-check-label"> <input class="form-check-input" asp-for="InvoiceHeader.InvoiceLines[0].LineIsTaxed" /> @Html.DisplayNameFor(model => model.InvoiceHeader.InvoiceLines[0].LineIsTaxed) </label> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceLines[0].LineTax" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceLines[0].LineTax" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceLines[0].LineTax" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="InvoiceHeader.InvoiceLines[0].LineTotal" class="control-label"></label> <input asp-for="InvoiceHeader.InvoiceLines[0].LineTotal" class="form-control" /> <span asp-validation-for="InvoiceHeader.InvoiceLines[0].LineTotal" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-page="Index">Back to List</a> </div>
3. 修复 ApplicationDbContext 语法错误
补上构造函数缺失的大括号:
public class ApplicationDbContext : IdentityDbContext { // 补上构造函数的方法体大括号 public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<Order> Order { get; set; } public DbSet<Vendor> Vendor { get; set; } public DbSet<Department> Department { get; set; } public DbSet<InvoiceHeader> InvoiceHeader { get; set; } public DbSet<InvoiceLine> InvoiceLine { get; set; } }
内容的提问来源于stack exchange,提问作者Bakr Albakri
相关产品推荐
相关产品推荐

