【发布时间】:2022-11-04 11:54:10
【问题描述】:
我有一个具有 ExternalSystemName 值对象和 Deployment 父类型的实体,它是另一个实体。模型的重要部分如下所示:
public sealed class ExternalSystem : Entity
{
public ExternalSystemName Name { get; private set; }
public Deployment Deployment { get; private set; }
}
此实体的唯一性由部署 ID(存储在部署实体类中)和名称(即 ExternalSystemName 值对象的值)的组合确定。换句话说,一个部署不能有两个同名的外部系统。
尝试使用 IEntityTypeConfiguration 实现设置此组合唯一索引时遇到问题:
internal sealed class ExternalSystemsConfiguration :
IEntityTypeConfiguration<ExternalSystem>
{
public void Configure(EntityTypeBuilder<ExternalSystem> builder)
{
builder.ToTable("TblExternalSystems");
builder.OwnsOne(e => e.Name, navigationBuilder =>
{
navigationBuilder.Property(e => e.Value)
.HasColumnName("Name");
});
builder.HasIndex(e => new { e.Name, e.Deployment }).IsUnique();
}
}
运行我的 API 时出现此异常:
System.InvalidOperationException: ''Name' cannot be used as a property on entity type 'ExternalSystem' because it is configured as a navigation.'
我尝试将索引指向 e.Name.Value ,但出现此错误:
System.ArgumentException: 'The expression 'e => new <>f__AnonymousType0`2(Value = e.Name.Value, Deployment = e.Deployment)' is not a valid member access expression. The expression should represent a simple property or field access: 't => t.MyProperty'. When specifying multiple properties or fields, use an anonymous type: 't => new { t.MyProperty, t.MyField }'. (Parameter 'memberAccessExpression')'
我还在其中一个属性上尝试了唯一索引,但无论如何我都会收到导航错误。我担心我已经知道答案,但这是否意味着 EF Core 仅支持非实体、非 valueObject 类型的列上的索引?这是否意味着我的模型需要一个代表部署 ID 的 Guid 属性而不是部署本身?
更新
我了解到 EF Core 可以很好地处理引用/原始对。考虑到这一点,我的 ExternalSystem 实体现在可以同时拥有这两个属性:
public Deployment Deployment { get; private set; }
public Guid DeploymentId { get; private set; }
该 Guid 属性不是构造函数的一部分,因为它们最终获得相同的列名,所以一切正常。我现在可以将其添加到该实体的配置中,并且索引已正确创建:
builder.HasIndex(e => new { e.DeploymentId}).IsUnique();
我现在的问题是值对象。使用相同的方法,我想我可以做这样的事情吗?
public ExternalSystemName NameV { get; private set; }
public string Name { get; private set; }
我必须重命名值对象属性,因为它们显然不能共享相同的名称。这与实体类型无关,因为 EF Core 知道首先将“Id”添加到列名。通过此设置,EF Core 正在复制列。一个具有名称“Name”,另一个具有“ExternalSystem_Name”。显然,其他一切都失败了,因为该列不接受空值。为什么会这样?
【问题讨论】:
-
将属性
NameId和DeploymentId添加到ExternalSystem并在这些属性上添加索引。 -
那么这些 Id 属性可以与关联的实体类型并行存在并与底层数据库一起使用吗?
-
是的,底层数据库应该已经有这些列,因为 FK 和 EF 知道如何处理引用/原始属性对(又名外键关联)。
-
这适用于实体类型,但我不确定如何以相同的方法处理值对象。我会更新我原来的帖子。
标签: c# entity-framework-core unique-constraint value-objects