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

注释EF Core关联配置后未触发预期Bug,是否为缓存问题?

问题:无法重现SQLite的NOT NULL约束异常

我有一个使用SQLite数据库的C#应用,曾触发以下异常:

Microsoft.EntityFrameworkCore.DbUpdateException: '保存实体更改时发生错误。请查看内部异常了解详细信息。'
内部异常:SqliteException: SQLite Error 19: 'NOT NULL constraint failed: RefreshTokens.AccountId'。

我通过在DbContext派生类中添加以下代码修复了该Bug:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Account>()
                .HasMany(e => e.RefreshTokens)
                .WithOne(e => e.Account)
                .IsRequired();
}

我想要复现该Bug,因此注释了这段代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // modelBuilder.Entity<Account>()
    //             .HasMany(e => e.RefreshTokens)
    //             .WithOne(e => e.Account)
    //             .IsRequired();
}

但代码仍正常运行,似乎存在某种缓存问题。我需要做些什么才能让该Bug重现?


相关代码

数据库更新代码(getRefreshToken方法及相关)

private (RefreshToken, Account) getRefreshToken(string token)
{
    var account = _context.Accounts
                          .Include(x => x.RefreshTokens)
                          .SingleOrDefault(u => u.RefreshTokens.Any(t => t.Token == token));
        
    if (account == null)
    {
        Console.WriteLine("Exception thrown");
        throw new AppException("Invalid token");
    }

    var refreshToken = account.RefreshTokens
                              .Single(x => x.Token == token);

    if (!refreshToken.IsActive) 
         throw new AppException("Invalid token");

    return (refreshToken, account);
}

public AuthenticateResponse RefreshToken(string token, string ipAddress)
{
    log.Info("RefreshToken before locking");
    Monitor.Enter(lockObject);

    using (IDbContextTransaction transaction = _context.Database.BeginTransaction())
    {
        try
        {
            var (refreshToken, account) = getRefreshToken(token);
                    
            _context.Update(account);
            _context.SaveChanges();

            transaction.Commit();

            return response;
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            Console.WriteLine(Thread.CurrentThread.Name + "Error occurred.");
            log.Error("RefreshToken:" + ex.Message);
            throw ex;
        }
        finally
        {
            Monitor.Exit(lockObject);
            log.Info("RefreshToken after locking");
        }
    }
}

namespace WebApi.Helpers
{
    public class DataContext : DbContext
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public DbSet<SystemInfo> SystemInformation { get; set; }

        public DbSet<Account> Accounts { get; set; }
        public DbSet<Schedule> Schedules { get; set; }

        public DbSet<Function> UserFunctions { get; set; }
        public DbSet<SchedulePoolElement> SchedulePoolElements { get; set; }
        
        public DbSet<RefreshToken> RefreshTokens { get; set; }

        private readonly IConfiguration Configuration;

        public DataContext(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
            // connect to sqlite database
            options.UseSqlite(Configuration.GetConnectionString("WebApiDatabase"));
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Account>().HasMany(e => e.RefreshTokens).WithOne(e => e.Account).IsRequired();
        }
    }
}

Account类

using System;
using System.Collections.Generic;

namespace WebApi.Entities
{
    public class Account
    { 
        public int Id { get; set; }
        public string Title { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }

        public List<RefreshToken> RefreshTokens { get; set; }
    }
}

RefreshToken类

using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations;

namespace WebApi.Entities
{
    [Owned]
    public class RefreshToken
    {
        [Key]
        public int Id { get; set; }
        public Account Account { get; set; }
        public string Token { get; set; }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:34:53