问题描述
我在 DataSeeding 中遇到了 EF Core 迁移问题。我有以下实体配置:
public void Configure(EntityTypeBuilder<ChartOptionsModel> builder)
{
builder.ToTable("charts_options");
//Columns description
builder.Property(s => s.Id)
.UseIdentityColumn()
.HasColumnName("id")
.HasColumnType("bigint");
builder.Property(s => s.GroupId)
.HasColumnName("group_id")
.HasColumnType("bigint")
.HasDefaultValue(1);
builder.Property(s => s.Type)
.HasColumnName("type")
.HasColumnType("varchar(50)")
.HasDefaultValue("");
builder.Property(s => s.Title)
.HasColumnName("title")
.HasColumnType("text")
.HasDefaultValue("");
builder.Property(s => s.LabelFormatter)
.HasColumnName("label_formatter")
.HasColumnType("text")
.HasDefaultValue("");
builder.Property(s => s.ShowChart)
.HasColumnName("show_chart")
.HasColumnType("boolean")
.HasDefaultValue(true);
//Keys
builder.HasKey(s => s.Id)
.HasName("charts_options_pkey");
//FK
builder.HasOne(s => s.Group)
.WithMany(s => s.ChartsOptions)
.HasForeignKey(s => s.GroupId)
.HasConstraintName("charts_options_group_id_fkey");
//Indices
builder.HasIndex(s => s.GroupId)
.HasDatabaseName("charts_options_group_id_idx");
builder.HasData(ChartsOptionsSeedingData.ChartsOptions);
}
当我使用 Add-Migration [Migration name]
创建迁移时,我在迁移的 BuildTargetModel
方法中得到了这个:
modelBuilder.Entity("DatabaseManagerService.Database.Models.Charts.ChartOptionsModel",b =>
{
//other fields
b.Property<bool>("ShowChart")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true)
.HasColumnName("show_chart");
b.Property<string>("Title")
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("")
.HasColumnName("title");
b.Property<string>("Type")
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasDefaultValue("")
.HasColumnName("type");
//other fields
b.ToTable("charts_options");
b.HasData(
new
{
Id = 1L,GroupId = 1L,LabelFormatter = "`${vals[0]} of ${vals[0] + vals[1]}`",ShowChart = false,Title = "AHU In Local",Type = "AHUInLocalChart"
},new
{
Id = 2L,Title = "FQC In Local",Type = "FQCInLocalChart"
},// other values here
);
});
在Up
方法中,建表没问题,但是插入数据很麻烦:
migrationBuilder.InsertData(
table: "charts_options",columns: new[] { "id","group_id","label_formatter","title","type" },values: new object[,]
{
{ 1L,1L,"`${vals[0]} of ${vals[0] + vals[1]}`","AHU In Local","AHUInLocalChart" },{ 21L,3L,"HТ OK","HTOkChart" },//rest of the values
});
问题是,虽然 ShowChart
属性的默认值是 true
,并且在模型快照中我有前两行数据的 ShowChart = false
,但生成的 { {1}} 语句,没有列 insert
,以及相应的值 - show_chart
。
是我做错了什么,还是这是预期的行为?
最好的问候,
朱利安
解决方法
经过长时间的搜索,我找到了发生这种情况的原因和解决方案。
Here 是解决方案的链接:
选项 使这更好的模式,例如使用默认为 true 的 bool。
A:使用客户端默认值 我们会搭建脚手架:
public class Blog
{
public bool IsValid { get; set; } = true;
}
和
.HasDefaultValue(true)
.ValueGeneratedNever();
(如果我们引入一个不包括所有数据库工件的脚手架模式,那么我们可以跳过这个。)
手动编写代码时,我们建议:
public class Blog
{
public bool IsValid { get; set; } = true;
}
并且没有存储生成的配置,除非您需要迁移来在数据库中创建默认值。
B:使用由可为空字段支持的常规属性 这种方法将以更多代码为代价保留所有存储生成的行为。此外,我们需要对 EF 进行更改以使其工作,但它们不应该很复杂。
脚手架和手动编写的代码是一样的:
public class Blog
{
private bool? _isValid;
public bool IsValid
{
get => _isValid ?? false;
set => _isValid = value;
}
}
和
.HasDefaultValue(true);
(应该不需要设置属性访问模式,因为我们在 3.0 中默认读取/写入字段。)
C:使用可为空的属性 这会保留存储生成的行为,但会强制模型中的类型可以为空。
public class Blog
{
public bool? IsValid { get; set; };
}
和
.HasDefaultValue(true);