sqlite 代码工作但应该失败,这是缓存问题吗?

k2fxgqgv  于 2023-08-06  发布在  SQLite
关注(0)|答案(1)|浏览(172)

我有一个使用SQLite数据库的C#应用程序,它生成了一个异常:
Microsoft.EntityFrameworkCore.DbUpdateException:'保存实体更改时出错。有关详细信息,请参见内部异常。'
内部异常:SqliteException:SQLite错误19:'NOT NULL约束失败:RefreshTokens.
我通过添加以下内容修复了这个bug(在从DbContext派生的类中):

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; }
    }
}

nimxete2

nimxete21#

您在“Account”和“RefreshTokens”之间创建了一个关系,并且您的外键“AccountId”为null,但您对“AccountId”的配置为“IsRequired”
这样试试

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

字符串

相关问题