R.S*_*lva 7 entity-framework-core
我正在尝试将DDD与EFCore结合使用,并且努力寻找一种方法来将代表同一实体的来自不同上下文的2个POCO映射到同一张表。
我在UserContext中有一个User类,其中包含为我的应用程序创建新用户所需的所有属性。而且我在OrderContext中有一个User类,在该类中我仅具有Id和Email属性,因为这是OrderContext需要的全部工作。
所以我有这样的事情:
modelBuilder.Entity<Domain.UserContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
u.OwnsOne(e => e.Name);
u.OwnsOne(b => b.HomeAddress);
});
modelBuilder.Entity<Domain.OrderContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
});
modelBuilder.Entity<Domain.OrderContext.Order>(p =>
{
p.ToTable("Order").HasKey(b => b.Id);
p.HasOne(x => x.User); // this is OrderContext.User
});
Run Code Online (Sandbox Code Playgroud)
我似乎找不到一种将两个User类映射到同一张表的方法。有办法吗?
Edit1:两个上下文都是有界上下文DDD的概念,而不是DbContext。我只需要将两个类映射为同一张表。Add-Migration命令返回一条消息,告诉我它无法将“ OrderContext.User”映射到表“ User”,因为它已经映射到“ UserContext.User”。
问题的主要原因是,EF Core无法弄清楚如何对2个不同的实体使用相同的表。映射中缺少数据,一旦填写,它就会按预期工作。
首先,您需要定义它们之间的关系。与相同的PK共享同一表在服务器端未定义外键,但是两个实体之间仍然存在一对一的内在关系,并且使用PK作为FK。定义关系后,您将看到它起作用,并且两个实体都映射到同一张表。(就像拥有实体如何映射到同一表一样)。不过,这可能并不代表您的情况已经结束。由于从EF角度来看,它们仍然是2个不同的实体,除了Id(或PK属性)外,它们将具有自己的列来存储数据。但是,如果您在两种情况下都有相同的列(例如Email在您的方案中)。在这种情况下,您还需要为这些其他列提供映射。如果您将它们明确映射到同一列,则它们将开始共享数据库中的列。总体来说,代码看起来像这样。
namespace UserContext
{
public class User
{
public int Id { get; set; }
public string Email { get; set; }
// Other properties
}
}
namespace OrderContext
{
public class User
{
public int Id { get; set; }
public string Email { get; set; }
}
}
// In OnModelCreating method
modelBuilder.Entity<UserContext.User>(u =>
{
u.ToTable("User");
u.Property(e => e.Email).HasColumnName("Email");
// Configuration for other properties
});
modelBuilder.Entity<OrderContext.User>(u =>
{
u.ToTable("User");
u.Property(e => e.Email).HasColumnName("Email");
u.HasOne<UserContext.User>().WithOne().HasForeignKey<OrderContext.User>(e => e.Id);
});
Run Code Online (Sandbox Code Playgroud)
上面的代码创建带有共享列的单个表,并且应该可以正常工作。如果需要,可以通过以下相同配置在同一表中添加更多实体。在这里,我User从UserContext主要方面使用,但是您可以使用任何一方。对我来说,主要的原因是UserContext.User将在添加新用户时添加的实体。共享表的实体也不必是子集。但是会有一些其他属性的列,这些列是不共享的。
@Smit 提供的解决方案应该可行,但对于孤立的有界上下文来说并不理想,其中每个上下文都不知道彼此,并且每个上下文都在处理自己的配置。
我通过为每个有界上下文添加单独的 DbContext 解决了这个问题。这些上下文中的每一个都继承基本 DbContext,其中我有共享逻辑(如审核等),并且有界上下文内的每个 DbContext 都有它自己的 DbSet 和 Fluent Api 配置。这样我就有了指向同一个表但来自不同 DbContext 的实体。
我自己也在看这个问题。我注意到,如果您为其中一个表指定架构名称,那么 EF 不会抱怨。例如你的情况:
modelBuilder.Entity<Domain.UserContext.User>(u =>
{
u.ToTable("User", "dbo").HasKey(e => e.Id);
u.OwnsOne(e => e.Name);
u.OwnsOne(b => b.HomeAddress);
});
modelBuilder.Entity<Domain.OrderContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
});
Run Code Online (Sandbox Code Playgroud)
当然,这不是一个完整的解决方案,甚至不是一个解决方法,因为您不能有超过 2 次提及“User”表(即,在超过 2 个上下文中)。
我还发现https://data.uservoice.com/forums/72025-entity-framework-core-feature-suggestions/suggestions/1872001-map-multiple-entities-to-same-table这让我认为这一般不可能。
关于 DDD 的一般情况
大多数消息来源表示,有界上下文不仅应该通过代码隔离,还应该通过数据隔离。从理论上讲,这意味着您的用户表应该在每个有界上下文中重复。这是理想的方法,但对于更简单的场景来说不必要地复杂(恕我直言),因为它涉及所有重复表之间的数据同步。
| 归档时间: |
|
| 查看次数: |
4588 次 |
| 最近记录: |