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

VS2022升级v17.2.2后EF Core插入Member误写Teams表报NULL错误

问题描述

升级Visual Studio 2022至v17.2.2版本后,ASP.NET应用突发SQL数据库插入错误,提示非空字段不允许空值无法完成插入操作。升级前从未出现该问题,甚至此前开发完成的同框架ASP.NET应用也出现了同类报错。
实际业务逻辑仅需要向Members表插入带TeamId的成员记录,完全不需要向Teams表写入任何数据,但抛出的核心错误为:无法向Tjoba-Server.dbo.Teams表的Class列插入NULL值,该列不允许为空,插入操作失败,语句已终止。

相关代码

实体模型定义

public class Member
{       
    public int MemberId { get; set; }

    [Required(ErrorMessage = "Dit is een verplicht veld")]
    public string FirstName { get; set; }
    [Required(ErrorMessage = "Dit is een verplicht veld")]
    public string LastName { get; set; }      
    public string MemberImage { get; set; }
    
    public Gender Gender { get; set; }
    public int TeamId { get; set; }

    public virtual Team Team { get; set; } = new();
}

定义最后一个virtual Team导航属性的目的,是查询Member时通过预加载关联拉取对应Team的关联数据。

关联查询逻辑

public async Task<IEnumerable<Member>> GetAllMembersByTeamId(int TeamId)
{
    var result = await dbContext.Members
                                .Include(t => t.Team)
                                .Where(t => t.TeamId == TeamId)
                                .ToListAsync();

    if (result != null)
    {
        return result;
    }
    else 
        return null;
}

成员写入逻辑

public class MemberRepository : IMemberRepository
{
    private readonly AppDbContext dbContext;

    public MemberRepository(AppDbContext dbContext)
    {
        this.dbContext = dbContext;
    }
   
    public async Task<Member> AddMember(Member obj)
    {
        await dbContext.Members.AddAsync(obj);
        await dbContext.SaveChangesAsync();
        return obj;
    }
}

页面提交逻辑

页面初始化时先查询待关联的团队信息:

protected async override Task OnInitializedAsync()
{
    Team = await TeamsRepository.GetTeamById(int.Parse(Id));
}

通过EditForm的OnValidSubmit事件触发提交逻辑:

public async Task HandleValidSubmit()
{
    ConfirmationTitle = StaticString.ConfirmationTitle;
    ConfirmationMessage = StaticString.ConfirmationMessage;

    Member.TeamId = int.Parse(Id);

    await MemberRepository.AddMember(Member);
    NavigationManager.NavigateTo("/adminpage");
}
报错信息

后端核心异常

Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Class', table 'Tjoba-Server.dbo.Teams'; column does not allow nulls. INSERT fails.
The statement has been terminated.

前端捕获异常

blazor.server.js:1 [2022-06-02T13:13:22.000Z] Error: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Class', table 'Tjoba-Server.dbo.Teams'; column does not allow nulls. INSERT fails.
The statement has been terminated.
The statement has been terminated.
ClientConnectionId:2df86c5d-9cee-4c70-ad12-ebb86a036fe9
Error Number:515,State:2,Class:16
Uncaught (in promise) Error: Cannot send data if the connection is not in the 'Connected' State.
问题根因

Member实体中给Team导航属性设置了默认初始化= new(),提交新增Member时,若Member实例携带的Team对象不是被当前DbContext跟踪的已存在实体,EF Core会将这个仅初始化了空对象、缺少Class等必填字段值的Team识别为待新增实体,执行SaveChangesAsync时会自动尝试向Teams表插入这条不完整的记录,最终触发非空约束报错。
升级VS2022到17.2.2时同步更新了内置的EF Core版本,新版本调整了关联实体的跟踪判定逻辑,因此之前可以正常运行的代码升级后批量出现同类问题。

修复方案

手动标记关联实体状态的方案可以生效,代码如下:

public async Task<Member> AddMember(Member member)
{
    if (member.Team != null)
    {
        dbContext.Entry(member.Team).State = EntityState.Unchanged;
    }
    var result =  await dbContext.Members.AddAsync(member);
    await dbContext.SaveChangesAsync();
    return result.Entity;         
}

更推荐的长期修复方式是:新增Member提交时,不要给导航属性绑定空的Team实例,仅给TeamId外键赋关联值即可,从根源上避免EF Core误将空导航属性识别为待新增实体。


内容的提问来源于stack exchange,提问作者Gerald

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 05:36:30