EfCore OwnsOne 种子可空对象失败
EfCore OwnsOne seed nullable objects failing
我想使用 EfCore 将数据播种到我拥有的实体中,这些实体可以是 nullable
实体:
public class RootEntity
{
protected RootEntity() { }
public Guid Id { get; set; }
public OwnedEntityLevel1? OwnedEntityLevel1 { get; set; } // can be nullable
}
public class OwnedEntityLevel1
{
public Guid Id { get; set; }
}
DbContext 的模型配置:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<RootEntity>(b =>
{
b.OwnsOne(x => x.OwnedEntityLevel1, ob =>
{
ob.HasData(RootEntity.All.Select(x => new
{ x.OwnedEntityLevel1?.Id, RootEntityId = x.Id }));
});
b.HasData(RootEntity.All.Select(x => new { x.Id }));
});
}
当我尝试创建迁移时:
dotnet ef migrations add Initial --context NullableObjectDbContext -o Migrations/NullableObject
我收到错误:
The seed entity for entity type 'OwnedEntityLevel1' cannot be added because no value was provided for the required property 'Id'.
消息显然是正确的。但我不明白你是否可以用 .HasData
以某种方式为可为 null 的对象播种?
我要播种的数据:
public static RootEntity PredefinedEntity11 { get; } =
new(
Guid.Parse("96e1d442-bdd0-4c6f-9d01-624b27abbac3"),
new OwnedEntityLevel1
{
Id = Guid.Parse("8f8eea73-0b43-412a-b0aa-a9338db6e067")
}
);
public static RootEntity PredefinedEntity12 { get; } =
new(
Guid.Parse("aae51dac-016e-472e-ad51-2f09f8cb9fbb"),
null! // When i add this the migration fails with The seed entity for entity type 'OwnedEntityLevel1' cannot be added because no value was provided for the required property 'Id'
);
public static IReadOnlyList<RootEntity> All { get; } =
new List<RootEntity>(new[] { PredefinedEntity11, PredefinedEntity12 }).AsReadOnly();
在我的正常程序流程中,我可以毫无问题地添加可为 null 的对象:
var ctx = new NullableObjectDbContext();
var rootEntity = new RootEntity(Guid.NewGuid(), null);
ctx.Add(rootEntity);
ctx.SaveChanges();
我在这里创建了一个最小的可复制示例:https://github.com/enterprisebug/EfCoreHasDataNestedOwnedTypes/tree/main/EfCoreHasDataNestedOwnedTypes/NullableObject
具有匿名类型的 Model data seeding 通过 名称和 type.
匹配属性
在你的情况下,即使种子类型 属性 称为 Id
,它的类型与种子实体的 Id
属性 的类型不同(Nullable<Guid>
从 ?.
运算符 vs Guid
推断),因此未映射并生成令人困惑的错误消息。
new
{
x.OwnedEntityLevel1?.Id, // Guid? Id
RootEntityId = x.Id // Guid RootEntityId
}
解决方案是通过首先过滤掉null
对象,以匿名类型生成并填充一个Guid Id
属性,例如(null 宽容运算符用于抑制 NRT 警告):
ob.HasData(RootEntity.All
.Where(x => x.OwnedEntityLevel1 != null)
.Select(x => new
{
x.OwnedEntityLevel1!.Id, // Guid Id
RootEntityId = x.Id // Guid RootEntityId
}));
我想使用 EfCore 将数据播种到我拥有的实体中,这些实体可以是 nullable
实体:
public class RootEntity
{
protected RootEntity() { }
public Guid Id { get; set; }
public OwnedEntityLevel1? OwnedEntityLevel1 { get; set; } // can be nullable
}
public class OwnedEntityLevel1
{
public Guid Id { get; set; }
}
DbContext 的模型配置:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<RootEntity>(b =>
{
b.OwnsOne(x => x.OwnedEntityLevel1, ob =>
{
ob.HasData(RootEntity.All.Select(x => new
{ x.OwnedEntityLevel1?.Id, RootEntityId = x.Id }));
});
b.HasData(RootEntity.All.Select(x => new { x.Id }));
});
}
当我尝试创建迁移时:
dotnet ef migrations add Initial --context NullableObjectDbContext -o Migrations/NullableObject
我收到错误:
The seed entity for entity type 'OwnedEntityLevel1' cannot be added because no value was provided for the required property 'Id'.
消息显然是正确的。但我不明白你是否可以用 .HasData
以某种方式为可为 null 的对象播种?
我要播种的数据:
public static RootEntity PredefinedEntity11 { get; } =
new(
Guid.Parse("96e1d442-bdd0-4c6f-9d01-624b27abbac3"),
new OwnedEntityLevel1
{
Id = Guid.Parse("8f8eea73-0b43-412a-b0aa-a9338db6e067")
}
);
public static RootEntity PredefinedEntity12 { get; } =
new(
Guid.Parse("aae51dac-016e-472e-ad51-2f09f8cb9fbb"),
null! // When i add this the migration fails with The seed entity for entity type 'OwnedEntityLevel1' cannot be added because no value was provided for the required property 'Id'
);
public static IReadOnlyList<RootEntity> All { get; } =
new List<RootEntity>(new[] { PredefinedEntity11, PredefinedEntity12 }).AsReadOnly();
在我的正常程序流程中,我可以毫无问题地添加可为 null 的对象:
var ctx = new NullableObjectDbContext();
var rootEntity = new RootEntity(Guid.NewGuid(), null);
ctx.Add(rootEntity);
ctx.SaveChanges();
我在这里创建了一个最小的可复制示例:https://github.com/enterprisebug/EfCoreHasDataNestedOwnedTypes/tree/main/EfCoreHasDataNestedOwnedTypes/NullableObject
Model data seeding 通过 名称和 type.
匹配属性在你的情况下,即使种子类型 属性 称为 Id
,它的类型与种子实体的 Id
属性 的类型不同(Nullable<Guid>
从 ?.
运算符 vs Guid
推断),因此未映射并生成令人困惑的错误消息。
new
{
x.OwnedEntityLevel1?.Id, // Guid? Id
RootEntityId = x.Id // Guid RootEntityId
}
解决方案是通过首先过滤掉null
对象,以匿名类型生成并填充一个Guid Id
属性,例如(null 宽容运算符用于抑制 NRT 警告):
ob.HasData(RootEntity.All
.Where(x => x.OwnedEntityLevel1 != null)
.Select(x => new
{
x.OwnedEntityLevel1!.Id, // Guid Id
RootEntityId = x.Id // Guid RootEntityId
}));