Я пишу модульный тест, который включает тестирование пробелов в столбцах идентификаторов. Я использую базу данных 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. Подумав, может быть, это поможет запустить Entity Framework для использования правильной модели, я реализовал это:
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, в результате чего сначала будет создана его модель, то, следовательно, заполнение никогда не будет использоваться в Entity Framework, даже если я использую SeedingDbContext.
Может кто-нибудь сказать мне, как заставить Entity Framework принудительно использовать построитель моделей, о котором я говорю?