Entity framework core EFCore将2个实体映射到同一个表

Entity framework core EFCore将2个实体映射到同一个表,entity-framework-core,Entity Framework Core,我正在尝试将DDD与EFCore结合使用,我正在努力找到一种方法,将代表同一实体的不同上下文中的2个POCO映射到同一个表 我在UserContext中有一个User类,包含为我的应用程序创建新用户所需的所有属性。 我在OrderContext中有一个用户类,在这个类中我只有Id和Email属性,因为它是OrderContext工作所需要的全部 所以我有这样的想法: modelBuilder.Entity<Domain.UserContext.User>(u =>

我正在尝试将DDD与EFCore结合使用,我正在努力找到一种方法,将代表同一实体的不同上下文中的2个POCO映射到同一个表

我在UserContext中有一个User类,包含为我的应用程序创建新用户所需的所有属性。 我在OrderContext中有一个用户类,在这个类中我只有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
        });
modelBuilder.Entity(u=>
{
u、 ToTable(“User”).HasKey(e=>e.Id);
u、 OwnsOne(e=>e.Name);
u、 OwnsOne(b=>b.家庭地址);
});
实体(u=>
{
u、 ToTable(“User”).HasKey(e=>e.Id);
});
实体(p=>
{
p、 ToTable(“Order”).HasKey(b=>b.Id);
p、 HasOne(x=>x.User);//这是OrderContext.User
});
我似乎找不到将两个用户类映射到同一个表的方法。有办法吗

Edit1:这两个上下文都是限定上下文DDD的概念,而不是DbContext。
我只需要将两个类映射为同一个表。添加迁移命令返回一条消息,告诉我它无法将“OrderContext.User”映射到表“User”,因为它已映射到“UserContext.User”。

我自己也在研究这个问题。我注意到,如果您为其中一个表指定模式名,那么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);
    });
modelBuilder.Entity(u=>
{
u、 ToTable(“User”,“dbo”).HasKey(e=>e.Id);
u、 OwnsOne(e=>e.Name);
u、 OwnsOne(b=>b.家庭地址);
});
实体(u=>
{
u、 ToTable(“User”).HasKey(e=>e.Id);
});
当然,这不是一个完整的解决方案,甚至不是一个解决方案,因为您最多只能提到两次“用户”表(即,在两个以上的上下文中)

我还发现这让我觉得这在一般情况下是不可能的

关于DDD的一般情况


大多数消息来源都说,您的有界上下文不仅应该通过代码来隔离,还应该通过数据来隔离。这在理论上意味着您的用户表应该在每个有界上下文中重复。这是一种理想的方法,但对于更简单的场景来说,这是不必要的复杂(imho),因为它涉及所有重复表之间的数据同步。

问题的主要原因是,EF Core无法确定如何为两个不同的实体使用同一个表。映射中缺少数据,一旦您填写了这些数据,它就会按预期工作

首先,您需要定义它们之间的关系。使用同一PK共享同一个表时,服务器端没有定义外键,但这两个实体之间仍然存在一对一的内在关系,并且使用PK作为FK。定义关系后,您将看到它是有效的,并且两个实体都映射到同一个表。(就像拥有的实体如何映射到同一个表一样)。但这可能不是您案例映射的结束。因为从EF的角度来看,它们仍然是两个不同的实体,除了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);
});
命名空间用户上下文
{
公共类用户
{
公共int Id{get;set;}
公共字符串电子邮件{get;set;}
//其他属性
}
}
命名空间OrderContext
{
公共类用户
{
公共int Id{get;set;}
公共字符串电子邮件{get;set;}
}
}
//在onmodel创建方法中
实体(u=>
{
u、 ToTable(“用户”);
u、 属性(e=>e.Email);
//其他属性的配置
});
实体(u=>
{
u、 ToTable(“用户”);
u、 属性(e=>e.Email);
u、 HasOne().WithOne().HasForeignKey(e=>e.Id);
});

上面的代码创建了一个带有共享列的表,应该可以按预期工作。如果需要,可以按照相同的配置在同一个表中添加更多实体。在这里,我使用了
UserContext
中的
User
作为主要方面,但您可以使用任何方面。我的主要理由是,
UserContext.User
将是在添加新用户时添加的实体。共享表的实体也不必是子集。但是会有不共享的附加属性列。

@Smit提供的解决方案应该可以工作,但对于孤立的有界上下文来说并不理想,因为它们彼此都不知道,并且各自负责自己的配置


我通过为每个有界上下文添加单独的DBContext解决了这个问题。这些上下文中的每一个都继承基本DbContext,在这里我有我的共享逻辑(如审计等),而有界上下文中的每个DbContext都有它自己的dbset和Fluent Api配置。这样,我就有了指向同一个表但来自不同DBContext的实体。

您的问题不完整。您是否有2个不同的DbContext派生类,或者您的上下文是某个应用程序级分区,它们都位于同一DbContext中?还有,你到底看到了什么问题?@Smit,刚刚编辑了这篇文章。当你需要高效地读取同一数据的不同视图时,这种限制也是不好的。例如,您可能有一个巨大的Users表,其中包含许多字段,但也希望仅检索用户的全名(例如,对于UI下拉列表)或用户的保险id或其他内容。现在,您必须为每个视图创建一个SQL视图,或者使用其他一些愚蠢的解决方法