在单元测试中使用Entity Framework 6手动为数据库植入种子

时间:2019-07-01 02:46:17

标签: c# entity-framework entity-framework-6 effort

我正在编写一个单元测试,该测试涉及测试标识列中的差距。我正在使用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中使用种子。

有人可以告诉我如何使实体框架强制使用我告诉它的模型构建器吗?

0 个答案:

没有答案