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

MSTest中使用UseInMemoryDatabase时List<string>需主键的问题排查

问题:使用InMemoryDatabase进行单元测试时,List属性触发“需要定义主键”错误

在使用MSTest编写单元测试、配置UseInMemoryDatabase时,出现错误:实体类型'List'需要定义主键。该错误仅在运行测试时出现,启动应用时无此问题,错误源自GameWord类的public List<string> WordProgress { get; set; } = new List<string>();属性。添加[NotMapped]特性可消除错误,但会导致对应数据库列消失。

相关代码

Context配置

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<FinalWord>()
        .HasMany(c => c.Games)
        .WithOne(e => e.FinalWord);

    modelBuilder.Entity<Game>()
        .HasMany(c => c.GameWords)
        .WithOne(e => e.Game);

    modelBuilder.Entity<Game>()
        .HasOne(c => c.FinalWord)
        .WithMany(e => e.Games);
    
    modelBuilder.Entity<Word>()
        .HasMany(c => c.GameWords)
        .WithOne(e => e.Word);

    modelBuilder.Entity<GameWord>()
        .HasOne(c => c.Game)
        .WithMany(e => e.GameWords);
    
    modelBuilder.Entity<GameWord>()
        .HasOne(c => c.Word)
        .WithMany(e => e.GameWords);
}

GameWord.cs

public class GameWord
{
  [Key]
  public int Id { get; set; }
  public List<string> WordProgress { get; set; } = new List<string>();
  
  [Required]
  public Word Word { get; set; }
  [Required]
  public Game Game { get; set; }
  public bool Finished { get; set; } = false;
}

测试代码

public UnitTest1()
{
    DbContextOptionsBuilder<LingoContext> dbOptions = new DbContextOptionsBuilder<LingoContext>()
        .UseInMemoryDatabase(
            Guid.NewGuid().ToString()
        );
        
    _context = new LingoContext(dbOptions.Options);
}

[TestMethod]
public void GetAllGames()
{
    var repo = new SqlGameRepo(_context);
    Game game1 = new Game();
    Game game2 = new Game();
    _context.Game.Add(game1);
    _context.Game.Add(game2);
    _context.SaveChanges();
    
    IEnumerable<Game> result = repo.GetAllGames();
    
    Assert.AreEqual(result.Count(), 2);
}

错误原因

  • InMemory数据库与生产数据库的处理逻辑差异:
    生产环境中你大概率使用的是SQL Server这类关系型数据库,EF Core会自动通过值转换器将List<string>序列化为JSON字符串存储在单个列中,或者将其视为拥有类型的集合,不会要求主键。但InMemory数据库不支持这种自动序列化,它会把List<string>当作独立的实体类型处理,而string本身没有主键属性,因此抛出错误。
  • 测试上下文未继承生产环境的配置:
    你的生产DbContext可能已经配置了针对WordProgress属性的自定义值转换器,但测试代码中创建InMemory上下文时,没有包含该配置,导致InMemory无法正确识别属性的处理方式,进而触发错误。

内容的提问来源于stack exchange,提问作者Bas van der Veen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:50:17