c# - 如何使用 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; }
}
使用上面的代码示例,我可以运行单独的命令来为 Parent 和 Child 创建迁移,并且表格看起来正确。
add-migration create-parent -c parentcontext
add-migration create-child -c childcontext
添加到实体的关系并添加最终迁移失败。
add-migration add-parent-child-fk -c childcontext
只有当我在不同的上下文中有子项和父项时才会出现问题。
我已经尝试在父项和子项中以不同的方式定义关系以映射地址字段,以便子项“理解”映射,但我无法避免任何我尝试过的 EF 错误。
示例项目在这里
解决方案
主要问题是不同的上下文。值对象(拥有的实体类型)只是一个结果 - 如果没有值对象,那么您将遇到另一个问题。
您似乎将您的设计基于一个错误的假设,即只有公开暴露的实体类DbSet
。但事实并非如此。还包括导航属性引用的实体,以及它们引用的实体等。
这是合乎逻辑的,因为 EF Core 上下文表示具有表和关系的数据库。EF Core 需要了解所有相关实体才能正确支持加载相关数据、查询(连接)、级联删除、表、列、主键和外键属性/列及其映射等。
EF Core 文档的包含和排除类型部分对此进行了说明:
DbSet
按照惯例,在您的上下文的属性中公开的类型包含在您的模型中。此外,OnModelCreating
方法中提到的类型也包括在内。最后,通过递归探索已发现类型的导航属性找到的任何类型也包含在模型中。
为您的 调整他们的示例ChildContext
,发现以下类型:
Child
因为它暴露在DbSet
上下文的属性中Parent
因为它是通过Child.Parent
导航属性发现的Address
因为它是通过Parent.PrimaryAddress
导航属性发现的
由于ChildContext
没有Parent
实体配置,EF 假定与Parent
(and Address
) 相关的所有内容都符合约定,因此例外。
Shorty,使用包含相关实体的单独上下文不是一个好主意。解决方案是将所有相关实体放在一个上下文中并对其进行维护。
查看使用的术语,您可能已经在 DDD 和有界上下文之后,但这些不适合 EF Core(通常在关系数据库中)模型。
推荐阅读
- python - 在 Python 脚本中运行 gcloud compute scp 命令
- javascript - 获取美元交易对的价值
- php - 表单在测试环境中发送,但在将其放入客户域时停止接收
- django - 如何在 Windows 上获取所有特定文件夹并获取所有具有特定扩展名的文件
- bash - 如何仅从目录中获取文件名而不是bash中的整个路径
- python - 模拟调用返回一个空列表
- python - 根据与行值的比较在 DataFrame 中创建新列
- r - 添加第一列日期
- python - 获取 NameError:名称“团队”未使用 Selenium Python 定义
- ios - IOS - 默认情况下不出现垂直滚动条+不起作用