EFCore将2个实体映射到同一张表 [英] EFCore Map 2 entities to same table

查看:835
本文介绍了EFCore将2个实体映射到同一张表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将DDCore与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); //这是OrderContext.User
});

我似乎找不到一种将两个User类映射到同一张表的方法。有办法吗?



Edit1:两个上下文都是有界上下文DDD的概念,而不是DbContext。
我只需要将两个类映射为同一张表。 Add-Migration命令返回一条消息,告诉我它无法将'OrderContext.User'映射到表'User',因为它已经映射到'UserContext.User'。

解决方案

出现问题的主要原因是,EF Core无法弄清楚如何对2个不同的实体使用相同的表。映射中缺少数据,一旦填写,数据就会按预期工作。



首先,您需要定义它们之间的关系。与相同的PK共享同一表并没有在服务器端定义外键,但是两个实体之间仍然存在一对一的内在关系,并且使用PK作为FK。定义关系后,您将看到它起作用,并且两个实体都映射到同一张表。 (就像拥有实体如何映射到同一表一样)。不过,这可能并不代表您的情况已经结束。由于从EF角度来看,它们仍然是2个不同的实体,除了Id(或PK属性)外,它们将具有自己的列来存储数据。但是,如果您具有在两种情况下都通用的列(例如您的方案中的 Email ),该怎么办?在这种情况下,您还需要为这些其他列提供映射。如果您将它们明确映射到同一列,则它们将开始共享数据库中的列。总体而言,代码看起来像这样。

 命名空间UserContext 
{
公共类用户
{
public int Id {get;组; }
公用字符串电子邮件{get;组; }
//其他属性
}
}

名称空间OrderContext
{
公共类用户
{
public int ID {get;组; }
公用字符串电子邮件{get;组; }
}
}

//在OnModelCreating方法
modelBuilder.Entity< UserContext.User>(u =>
{
u.ToTable( User);
u.Property(e => e.Email).HasColumnName( Email);
//其他属性的配置
});

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);
});

上面的代码创建带有共享列的单个表,并且应该按预期工作。如果需要,可以通过以下相同配置在同一表中添加更多实体。在这里,我使用了 UserContext 中的 User 作为主要方面,但是您可以使用任何方面。对我来说,主要原因是 UserContext.User 是将在添加新User时添加的实体。共享表的实体也不必是子集。但是会有一些其他属性无法共享的列。


I'm trying to use DDD with EFCore and I am struggling to find a way to map 2 POCOs from different context that represent the same entity to the same table.

I have a User class inside UserContext, with all the properties needed to create a new user to my application. And I have either a User class inside my OrderContext, in this class I only have the Id and Email properties, cause it's all that is needed in OrderContext to work.

So I have something like this:

        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
        });

I can't seem to find a way to map both User classes to the same table. Is there a way to do it?

Edit1: Both contexts are bounded context DDD's concept not DbContext. I just need both classes to be maped as the same table. The Add-Migration command return a message telling me that it cannot map 'OrderContext.User' to table 'User' since it is already mapped to 'UserContext.User'.

解决方案

The main cause of issue is, EF Core cannot figure out how to use same table for 2 different entities. There is lack of data in mapping, once you fill that in, it works as expected.

First you will need to define how are they related to each other. Sharing same table with same PK does not have Foreign Key defined on server side but there is still intrinsic relationship between both entities which is one-to-one and using PK as FK. Once you define relationship, you will see that it works and both entities are mapped to same table. (Just like how owned entities are mapped to same table). This may not be end of mapping for your case though. Since from EF perspective they are still 2 different entities, except for Id (or PK property), they will have own columns to store data. But what if you have columns which are common in both the context (like Email in your scenario). In such case, you would need to provide mapping for those additional column too. If you map them to same column explicitly, they will start sharing the column in database. Overall the code would look like this.

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);
});

Above code creates single table with shared columns and should work as expected. You can add more entities in the same table if you want by following same configuration. Here, I used User from UserContext as principal side but you can use any side. The main reasoning for me was, UserContext.User will be the entity which will be added when adding new User. Entities sharing the table do not have to be subset either. But there will be columns for additional properties which are not shared.

这篇关于EFCore将2个实体映射到同一张表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆