现状
你好,我有一个dotnet标准库
EF核心2.1.1
(代码优先方法)访问持久层。要创建迁移,我使用一个单独的dotnet核心控制台应用程序(在同一个解决方案中),该应用程序包含
IDesignTimeDbContextFactory<T>
实施。
有必要播种一些数据,我想以一种舒适的方式来实现它,因为将来要播种的数据将被扩展或修改。因此在实施中
IEntityTypeConfiguration
我使用扩展方法
.HasData()
它获取要播种的对象数组。数组将从一个单独的类提供(
TemplateReader
,它从json文件加载对象(在该文件中将完成扩展和修改工作)。因此,可以修改json文件的内容并添加新的迁移,该迁移将包含要插入的生成代码(
modelBuilder.InsertData()
),更新(
modelBuilder.UpdateData()
)或删除(
modelBuilder.DeleteData()
)陈述。
因为我不会发送json文件,并且我希望避免加载序列化数据以进行种子设定和执行
.hasdata()
,我想使用
bool
将被赋予的价值
DbContext
由构造器。
如果不需要为迁移调用种子,则避免使用bool值(和
.hasdata()
)我用默认值false实现了一个重载构造函数。
此外,我不会使用
OnConfiguring
因为我要灵活设置
DbContextOptions<T>
对象或单独进行测试。
代码
下面的代码包含重命名的变量,以便对项目内容更加匿名,但表示当前实现的逻辑。
MyDesignTimeDbContextFactory
以下内容:
public class MyDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
public MyDbContext CreateDbContext(string[] args)
{
var connectionString = ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString;
var contextOptionsBuilder = new DbContextOptionsBuilder<MyDbContext>()
.UseSqlServer(connectionString);
return new MyDbContext(contextOptionsBuilder.Options, true);
}
}
MyDbContext
以下内容:
public sealed class MyDbContext : DbContext
{
private readonly bool _shouldSeedData;
public DbSet<Content> Contents { get; set; }
public DbSet<Template> Templates { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options, bool shouldSeedData = false) :
base(options)
{
ChangeTracker.LazyLoadingEnabled = false;
_shouldSeedData = shouldSeedData;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("mySchema");
modelBuilder.ApplyConfiguration(new TemplateTypeConfiguration(_shouldSeedData));
base.OnModelCreating(modelBuilder);
}
}
模板类型配置
以下内容:
public class TemplateTypeConfiguration : IEntityTypeConfiguration<Template>
{
private readonly bool _shouldSeedData;
public TemplateTypeConfiguration(bool shouldSeedData)
{
_shouldSeedData = shouldSeedData;
}
public void Configure(EntityTypeBuilder<Template> builder)
{
builder.Property(p => p.ModuleKey)
.IsRequired();
builder.Property(p => p.Html)
.IsRequired();
if (_shouldSeedData)
{
// reads all templates from configuration file for seeding
var templateReader = new TemplateReader(Directory.GetCurrentDirectory());
var templates = templateReader.GetTemplates().ToArray();
builder.HasData(templates);
}
}
}
模板
(
实体
)以下内容:
public class Template
{
public int Id { get; set; }
public string ModuleKey { get; set; }
public string Html { get; set; }
public virtual ICollection<Content> Contents { get; set; }
}
问题
据我所知我已经测试了
OnModelCreating(ModelBuilder)
将在构造函数中设置构造函数的bool值之前调用(
_shouldSeedData = shouldSeedData;
)中。那是因为
基本构造函数
会马上打电话给我,然后是我的。因此
_shouldSeedData
的值为
false
什么时候给
TemplateTypeConfiguration
是的。
因此,一个
Add-Migration
如果我修改了上面提到的json文件,将导致一个没有任何逻辑的“空”迁移。
已经测试过的方法
我已经试过用
IModelCacheKeyFactory
有自己的
ModelCacheKey
反对没有任何成功。作为模板,我用了这个
SO-question
是的。
我测试的另一种方法是
_应该播种数据
作为
public static
变量并将其设置为
MyDesignTimeDbContextFactory
到
true
,但在我看来,这是一个非常肮脏的解决方案,我希望避免在生产代码中实现。
也可以使用
DbContextOptionsBuilder<T>
的
UseModel(IModel)
避免使用
OnModelCreating
以及初始化
模板类型配置
有需要的
shouldSeedData = false
是的。这种方法的缺点是重复的代码在
模板类型配置
的构造函数值。在我看来,这和公众的静态做法一样令人讨厌。
问题
有没有一个干净的解决方案来实现
_应该播种数据
建造商认为
模型创建
可以用正确的值(
真的
)在设计时间?
在生产过程中
假
并提到
模板管理员
在里面
模板类型配置
不应因为if条件而调用。