猿问

如何使用 ValueObjects 定义嵌套模型关系

我有一个父子关系,其中父级有一个 ValueObject,但我无法确定如何正确定义该关系。


为子/父关系添加迁移失败并出现错误...


实体类型“地址”需要定义主键。


以下是当前的代码结构。


public class Address

{

        [Required]

        public string BuildingNumber { get; private set; }

        

        // other address properties...

}

public class Parent

{

        [Key]

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

        public int Id { get; protected set; }


        [Required]

        public Address PrimaryAddress { get; private set; }

}

public class ParentContext : DbContext

{

    public ParentContext(DbContextOptions<ParentContext> options) : 

     base(options)

    {

    }


    public DbSet<Parent> Parents { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)

    {

        base.OnModelCreating(modelBuilder);


        modelBuilder.Entity<Parent>().OwnsOne(p => p.PrimaryAddress);


        // Flatten the ValueObject fields into table

        modelBuilder.Entity<Parent>().OwnsOne(p => p.PrimaryAddress).

            Property(b => b.BuildingNumber).IsRequired().

                HasColumnName("Primary_BuildingName");

     }

}

public class Child

{

        [Key]

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

        public int Id { get; protected set; }


        [Required]

        public int ParentId { get; private set; }


        [ForeignKey("ParentId")]

        public Parent Parent { get; private set; }

}

public class ChildContext : DbContext

{

    public ChildContext(DbContextOptions<ChildContext> options) : base(options)

    {

    }


    public DbSet<Child> Children { get; set; }

}

使用上面的代码示例,我可以运行单独的命令来为父级和子级创建迁移,并且表看起来正确。

添加迁移创建父-c 父上下文

添加迁移创建子-c子上下文

添加与实体的关系并添加最终迁移失败。

添加迁移添加父子fk -c子上下文

仅当我的子级和父级处于不同的上下文中时,才会出现此问题。

我尝试在父级和子级中以不同的方式定义关系来映射地址字段,以便子级“理解”映射,但我无法避免我尝试过的任何方法出现 EF 错误。

示例项目在这里

https://github.com/cimatt55/ef-parent-valueobject


HUWWW
浏览 82回答 1
1回答

饮歌长啸

主要问题是不同的上下文。值对象(拥有的实体类型)只是一个结果 - 如果没有值对象,那么您将会遇到另一个问题。您的设计似乎基于一个错误的假设,即只有来自公开暴露的实体类DbSet。但事实并非如此。还包括导航属性引用的实体,以及它们引用的实体等。这是合乎逻辑的,因为 EF Core 上下文表示具有表和关系的数据库。EF Core 需要了解所有相关实体,以便正确支持加载相关数据、查询(联接)、级联删除、表、列、主键和外键属性/列及其映射等。EF Core 文档的包含和排除类型部分对此进行了解释:按照约定,上下文属性中公开的类型DbSet将包含在模型中。此外,OnModelCreating还包括方法中提到的类型。最后,通过递归探索已发现类型的导航属性找到的任何类型也包含在模型中。调整他们的示例ChildContext,发现以下类型:Child因为它暴露在DbSet上下文的属性中Parent因为它是通过Child.Parent导航属性发现的Address因为它是通过Parent.PrimaryAddress导航属性发现的由于ChildContext没有实体配置,EF 假定与( 和)Parent相关的所有内容均符合约定,因此出现例外。ParentAddressShorty,使用包含相关实体的单独上下文不是一个好主意。解决方案是将所有相关实体放在一个上下文中并进行维护。查看所使用的术语,您可能关注的是 DDD 和有界上下文,但这些不适合 EF Core(通常在关系数据库中)模型。
随时随地看视频慕课网APP
我要回答