我正在编写一个单元测试,该测试涉及测试标识列中的差距。我正在使用EFFORT的内存数据库在Entity Framework 6下进行测试,并尝试在单元测试开始时为数据库添加种子。
这是数据库示例布局:
public class ProdDbContext : DbContext
{
public ProdDbContext(DbConnection existingConnection, bool contextOwnsConnection);
public DbSet<One> One { get; set; }
public DbSet<Two> Two { get; set; }
}
public class One
{
public One();
[Key] public int Id { get; set; }
[ForeignKey("Two")] public int? TwoId { get; set; }
public virtual Two Two { get; set; }
}
public class Two
{
public Two();
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
}
当然,尝试做Two.Add()会忽略我专门设置的ID。因此,在阅读了有关此内容的更多信息之后,我发现了OnModelCreating,它允许单独的DbContext使用不同的模型构建器:
public class SeedingDbContext : ProdDbContext
{
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
dbModelBuilder.Entity<One>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
dbModelBuilder.Entity<Two>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
base.OnModelCreating(dbModelBuilder);
}
}
public class NonSeedingDbContext : ProdDbContext
{
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
// Method is for test only (i.e. setting a breakpoint)
base.OnModelCreating(dbModelBuilder);
}
}
我可以在两个OnModelCreating内设置一个断点,并看到两个断点都被击中。因此,我继续进行测试,并在前面进行了播种(即,两个ID一起加),是的,它确实进行了播种。但是不幸的是,在播种后,当测试使用非播种DbContext执行生产代码时,DbContext仍然具有Id自动递增功能,就好像它仍在播种一样(由于尝试使用Id零,因此失败)。我可以在生产代码中放置一个断点,并看到它正在使用NonSeedingDbContext,但是它没有使用为此创建的模型。
因此,在寻找答案时,我遇到了IDbModelCacheKeyProvider和CacheKey。我实现了它,认为这可能会帮助触发实体框架使用正确的模型:
public class SeedingDbContext : ProdDbContext, IDbModelCacheKeyProvider
{
public string CacheKey => nameof(SeedingDbContext);
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
dbModelBuilder.Entity<One>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
dbModelBuilder.Entity<Two>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
base.OnModelCreating(dbModelBuilder);
}
}
public class NonSeedingDbContext : ProdDbContext, IDbModelCacheKeyProvider
{
public string CacheKey => nameof(NonSeedingDbContext);
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
// Method is for test only (i.e. setting a breakpoint)
base.OnModelCreating(dbModelBuilder);
}
}
不幸的是,这似乎没有任何作用。
此行为也相反。如果我尝试首先使用NonSeedingDbContext,从而首先创建它的模型,那么即使我使用SeedingDbContext,也不会在Entity Framework中使用种子。
有人可以告诉我如何使实体框架强制使用我告诉它的模型构建器吗?