entity-framework-core - EfCore OwnsOne 种子可为空对象失败

标签 entity-framework-core ef-code-first

我想使用 EfCore 将数据播种到我拥有的实体,这些实体可以可为空

实体:

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 播种可空对象?

我试图播种的数据:

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匿名类型按名称和类型匹配属性。

在您的情况下,即使种子类型具有名为 Id 的属性,其类型与 Id 的类型不同种子实体的属性( Nullable<Guid>?. 运算符与 Guid 推断),因此未映射并生成令人困惑的错误消息。

new
{ 
    x.OwnedEntityLevel1?.Id, // Guid? Id
    RootEntityId = x.Id      // Guid RootEntityId 
}

解决方案是生成并填充 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
    }));

关于entity-framework-core - EfCore OwnsOne 种子可为空对象失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70076918/

相关文章:

entity-framework-core - 是否可以在 EF Core 3.1 中的 Table-Per-Hierarchy 表上调用存储过程?

c# - 使用 EF Core 2 和 Nlog 记录生成的 SQL

database - Entity Framework 6 复合键(DateTime + 外键)

c# - 无法首先从 EF 代码打开生成的数据库

c# - 实体类型 'Configuration' 需要定义主键

c# - Entity Framework Core 比较两个子集合属性

asp.net-core - ASP.NET Core SQL 连接超时

ef-code-first - 如何将 EF 核心脚手架到现有数据库?

c# - 如何使 ViewModel 验证与模型验证保持同步?

entity-framework - Entity Framework 4.1代码优先自引用一对多和多对多关联