Jan*_*kan 8 c# domain-driven-design entity-framework-core
互联网上的好心人大家好:)
我正在尝试使用 EF Core 5 实体作为 DDD 意义上的域实体。
我有两个实体的案例,每个实体都有自己的标识(意味着它们是 DDD 对象的实体类型,而不是 ValueObjects):国家和货币。
货币可以属于许多国家(例如欧元)。另一方面,国家只能拥有一种“当前活跃”货币,该货币不一定始终是同一货币(例如欧盟国家,放弃本国货币而使用欧元)。
在特定的域边界上下文中,我只需要:
public class Country : Entity<Guid>
{
public string Name { get; private set; }
// the rest is omitted for readability
public Currency Currency { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
和
public class Currency : Entity<Guid>
{
public string Name { get; set; }
public string Code { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我不想public ICollection<Country> Countries { get; private set; }在货币实体上拥有导航属性:只是为了能够定义 1:N 关系,因为这只会污染我的域。
我尝试将导航属性添加为 EF 影子属性,但 EF 不允许这样做,并抛出异常:
无法将导航“Countries”添加到实体类型“Currency”,因为基础类型上没有相应的 CLR 属性,并且无法在影子状态下添加导航属性。
货币不能由国家/地区拥有(在 EF 意义上为 OwnsOne),因为这意味着货币必须在数据库中具有复合的 {Id, IdCountry} PK,这将违反能够分配一种货币的要求到多个国家。
是否有一种解决方案可以在货币和国家/地区之间建立关系(或相反),该解决方案不会用导航属性污染域并允许将相同的 CLR 对象用作域和 EF 实体?
我正在尝试使用 EF Core 5 实体作为 DDD 意义上的域实体。
EF 实体表示所谓的数据模型,通常与领域/业务模型不同,有自己的需求/建模规则,与其他模型不同,导航属性是很好的关系表示,允许生成不同类型的查询,而无需使用手动连接等
因此,一般来说,您应该使用单独的模型,并在需要时在两者之间进行映射,从而不会“污染”您的域模式或违反其规则。就像遵循域模型规则一样,您应该遵循数据模型规则 - 我不明白为什么人们认为 EF 应该遵循他们的规则,而不是他们遵循 EF 规则。
无论如何,话虽这么说,虽然超级有用,但 EF Core 导航属性不是强制性的(除了目前通过隐式联结实体进行的多对多和跳过导航) - 您可以同时拥有两者,只是主要的,只是依赖的,甚至两者都没有。
您所需要做的就是定义与正确 Has/对的关系With。正确的方法是在存在时使用传递导航属性,在不存在时忽略它。
在这种情况下,你可以使用这样的东西:
modelBuilder.Entity<Country>()
.HasOne(e => e.Currency) // reference navigation property
.WithMany() // no collection navigation property
.IsRequired(); // omit this for optional relationship (to allow null FK)
Run Code Online (Sandbox Code Playgroud)
如果从另一端启动配置也可以实现同样的效果。在这种情况下,您必须显式提供泛型类型参数,因为它无法自动推断:
modelBuilder.Entity<Currency>()
.HasMany<Country>() // no collection navigation property
.HasOne(e => e.Currency) // reference navigation property
.IsRequired(); // omit this for optional relationship (to allow null FK)
Run Code Online (Sandbox Code Playgroud)
您可以使用任何一种方式,只是不要同时使用两种方式,因为它是一个且相同的关系,因此应该只配置一次以避免配置冲突(如果一个人使用IEnityTypeConfiguration<TEntity>与关系不太适合的单独的类 -一种关系有两端)。