gpt4 book ai didi

c# - EF Core 2.1 中的动态数据播种迁移生成取决于在 OnModelCreating() 中使用的 DbContext bool-flag

转载 作者:太空狗 更新时间:2023-10-30 01:13:11 25 4
gpt4 key购买 nike

现状

你好,我有一个 dotnet 标准库,我在其中使用 EF Core 2.1.1(代码优先方法)来访问持久层。为了创建迁移,我使用了一个单独的 dotnet 核心控制台应用程序(在同一解决方案中),其中包含 IDesignTimeDbContextFactory<T>实现。
有必要播种一些数据,我想以一种舒适的方式实现它,因为将来要播种的数据将被扩展或修改。因此在实现IEntityTypeConfiguration我使用扩展方法 .HasData()它获取要播种的对象数组。该数组将由一个单独的类 ( TemplateReader ) 提供,该类从 JSON 文件加载对象(将在其中完成扩展和修改工作)。因此,可以修改 JSON 文件的内容并添加一个新的迁移,该迁移将包含生成的代码到插入(modelBuilder.InsertData())、更新(modelBuilder.UpdateData())或删除(modelBuilder.DeleteData())语句。
因为我不会发送 JSON 文件并且我想避免加载序列化数据以进行播种和执行 .HasData() , 我想用 bool将赋予 DbContext 的值由构造函数。
为了避免在不需要为迁移调用种子设定(和 .HasData() )时使用 bool 值,我有一个重载的构造函数,它使用默认值 false 实现。此外,我不会使用 OnConfiguring因为我想灵活地设置DbContextOptions<T>在我的 IoC 容器中或单独进行测试的对象。


代码

以下代码包含重命名的变量,以更加匿名地描述项目内容,但代表当前实现的逻辑。

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; )。那是因为 base constructor 将被立即调用,然后是我的。因此 _shouldSeedData的值为 false什么时候给TemplateTypeConfiguration .
正因为如此,一个 Add-Migration如果我对上述 JSON 文件进行了任何修改,则会导致没有任何逻辑的“空”迁移。


已经测试过的方法

我已经尝试使用 IModelCacheKeyFactory拥有自己的ModelCacheKey没有任何成功的对象。作为模板,我使用了这个 SO-question .

我测试的另一种方法是设置 _shouldSeedData作为public static变量并从 MyDesignTimeDbContextFactory 设置它至 true ,但在我看来,这是一个非常肮脏的解决方案,我想避免在生产代码中实现。

应该也可以使用 DbContextOptionsBuilder<T>UseModel(IModel)避免使用 OnModelCreating 的扩展方法并初始化 TemplateTypeConfiguration需要 shouldSeedData = false .这种方法的一个缺点是有重复的代码,这些代码在 TemplateTypeConfiguration 中会有所不同。的构造函数值。在我看来,与公共(public)静态方法一样令人讨厌。


问题

是否有一个干净的解决方案来实现设置 _shouldSeedData通过 OnModelCreating 的构造函数可以在设计时以正确的值 ( true ) 使用它吗?
在生产中它应该是false并提到 TemplateReaderTemplateTypeConfiguration由于 if 条件,不应调用。

最佳答案

OnModelCreating 不是 由基本 DbContext 构造函数调用触发,因此保存传递给类成员的参数绝对没有问题。

在您的具体场景中,OnModelCreating 是通过在存储传递的参数之前访问 ChangeTracker 属性触发的:

public MyDbContext(DbContextOptions<MyDbContext> options, bool shouldSeedData = false) :
base(options)
{
ChangeTracker.LazyLoadingEnabled = false; // <--

_shouldSeedData = shouldSeedData;
}

只需交换线路即可解决问题。通常,始终在访问任何上下文属性之前初始化您的类成员。

关于c# - EF Core 2.1 中的动态数据播种迁移生成取决于在 OnModelCreating() 中使用的 DbContext bool-flag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51168127/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com