我使用值对象来封装验证,比如maxLength。这是一个没有工厂方法和验证的样本类的摘录:
public class CallingName : ValueObject
{
public string Value { get; }
public const int MaxLength = 50;
private CallingName(string text)
{
Value = text;
}
...
}
在SQL数据库中,表应具有类型为nvarchar
的字段"CallingName",最大长度为50。
使用EF Core,我知道值转换器和拥有的类型,但我不完全理解两者之间的选项和差异。如果一个值对象只有一个属性,是否可以使用其中任何一个?
到目前为止,我使用了一个字段的值转换器:
entity.Property(e => e.CallingName)
.HasMaxLength(CallingName.MaxLength)
.HasConversion(DBConverter.CallingNameConverter);
看看微软文档中的简单例子,我认为这应该在没有像这样的值转换器的情况下工作
entity.OwnsOne(e => e.CallingName)
.Property(e => e.Value)
.HasColumnName("CallingName")
.HasMaxLength(CallingName.MaxLength);
或
entity.OwnsOne(e => e.CallingName,
p=>p.Property<string>("CallingName")
.HasMaxLength(CallingName.MaxLength));
或
entity.OwnsOne(e => e.CallingName,
p => p.Property(e=>e.Value)
.HasColumnName("CallingName")
.HasMaxLength(CallingName.MaxLength));
以上所有版本都有效吗?不同版本的目的是什么?使用值转换器或拥有类型的情况或标准是什么?
据我所知,当类型没有公共setter时,它们需要为所拥有的类型提供一个空构造函数。值转换器可以分别调用构造函数。工厂方法。这是正确的吗?
OwnsOne的文档显示了6个重载,但没有示例。对我来说,这些描述听起来像克林贡语。我不明白每一个都是为了什么。我在谷歌上找不到比这更好的解释或文章了。有没有一个很好的例子解释?
我也在github上的dotnet核心问题中发布了这个问题。飞行员回答:
Owned类型是具有键属性的实体类型由该键的值标识。(EF可能会隐藏此键值您,但它仍然存在,并影响使用对象。(就DDD而言,它们旨在支持骨料,所有者充当骨料根。他们没有适用于DDD值对象,因为它们由键,这违背了价值对象的原则。
使用值转换器意味着属性仍然映射为属性,并且没有键。这意味着具有值转换器本质上具有值对象语义比自有类型更适合。
据我所知,在EF Core 7之前,拥有类型仍然是具有多个属性的值对象的唯一选项。
我还没有找到OwnsOne重载的解释以及为什么要使用每一个重载。
微软表示:
以前是拥有实体的团队视图总支持,也将是价值的合理近似值对象。经验表明情况并非如此。因此,在EF8,我们计划引入更好的体验,专注于领域驱动设计中的值对象。这种方法将基于价值转换器而非自有实体。
因此,我认为我们应该改用值转换器。我个人使用了Owned Types,但使用Owned Types值对象创建多列唯一索引是非常困难的。所以我也将切换到转换器。