在此问题中,如果我使用 Entity 一词,则是指DDD实体,除非我明确声明我在谈论EF核心实体< / em>
我一直在阅读Microsoft's documentation关于.NET Core的DDD模式。
我还一直在研究他们创建的GitHub repo,其中包含上述文档中描述的实现。具体来说,我正在查看in.next()
聚合(链接指向的位置)。
问题的背景
我试图了解它们如何实现Order.cs
属性。
如您所见,Enumeration
类型类似于值对象,但是是建模行为类似于枚举的更方便的方法(imho)。
使用Enumeration
类型的DDD实体的摘录(完整的实体在上面的repo链接中):
Enumeration
问题
以这种方式实现属性意味着,每当您public class Order
: Entity, IAggregateRoot
{
public OrderStatus OrderStatus { get; private set; }
private int _orderStatusId;
public Order()
{
_orderStatusId = OrderStatus.Submitted.Id;
}
}
get
属性时,它就是OrderStatus
。
我知道将实体封装在DDD中是头等大事,但是可以肯定的是,只有在修改状态时才需要担心。实施null
方法似乎只是读取属性值的一种很简单的方法:
GetOrderStatus
我想到的唯一一件事就是实现如下所示的属性,但这破坏了EF Core:
public class Order
: Entity, IAggregateRoot
{
public OrderStatus OrderStatus { get; private set; }
private int _orderStatusId;
public Order()
{
_orderStatusId = OrderStatus.Submitted.Id;
}
public OrderStatus GetOrderStatus()
{
return Enumeration.FromValue<OrderStatus>(_orderStatusId);
}
}
有没有更清洁的方法来实现这一目标?
答案 0 :(得分:0)
如果它是值类型,为什么不将其视为值类型(在EF核心术语Owned Entity中)?
拥有的类型基本上是没有身份的类型(它们不是由ID标识,而是由其整个值标识)。在幕后,所有拥有类型的属性都将转换为拥有实体的列名。
这是将值类型映射到关系数据库的绝佳方法,您不必在模型中添加标识(id)列。常见的示例是订单上的Address
。
如果这不能满足您的需求,则可以使用Value Converter将类型转换为数据库可以理解的类型(即enum->字符串而不是enum id)。这可用于将id(或字符串)转换为适当的值类型并进行分配。
通常,您的问题来自于将持久性知识泄漏到您的域中,__orderStatusId
与关系存储相关,在您的域中绝对没有意义。在设计DDD模型时,您绝对必须避免这种情况。
DDD模型永远不会受到持久性技术的影响(例如,具有数据库或ORM映射器所需的构造函数,具有值类型的ID,因为它们“映射”到数据库表等)。
使用转换器,您可以将值类型转换为id并将id转换为值类型,并使用
var converter = new ValueConverter<OrderStatus, int>(
v => v.Id,
v => Enumeration.FromValue<OrderStatus>(v));
modelBuilder
.Entity<Order>()
.Property(e => e.OrderStatus)
.HasConversion(converter);