You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 02:45:02