Entity Framework 代码优先:在具有不同连接列的实体中展平组合

Entity Framework Code First : flatten composition in entity with different join column

我在使用 EntityFramework 使用 Code First 配置时遇到问题。 我有两个表:

+---------------+        +-------------+
|  T_CONTRACTS  |        |  T_PERSONS  |
|---------------|        |-------------|
|CONTRACT_ID    |        |PERSON_ID    |
|CUSTOMER_ID    |        |NAME         |
+---------------+        +-------------+

我想要一个 EF 实体:

public class Contract
{
    public int ContractId { get; set; }
    public int CustomerId { get; set; }
    public string CustomerName { get; set; }

}

现在,我想将我的两个表映射到我的实体上。我命令这样做,我使用了 EntityTypeConfiguration。

public class ContractConfiguration : EntityTypeConfiguration<Contract>
{
    public ContractConfiguration()
    {
        ToTable("T_CONTRACTS", "ASSUROL"); //table and schema ALWAYS in uppercase
        HasKey(c => c.ContractId);
        Property(c => c.ContractId).HasColumnName("CONTRACT_ID").IsRequired();
        Property(c => c.CustomerId).HasColumnName("CUSTOMER_ID").IsRequired();

        // TODO : WIP, no idea of what i am doing
        HasRequired(c => c.CustomerName).WithRequiredPrincipal().Map( ca => {
            ca.MapKey("PERSON_ID");
            ca.ToTable("T_PERSONS", "ASSUROL");

            //Property(c => c.CustomerName).HasColumnName("NAME");
        });

    }
}

废话来了,我不知道如何实现映射。

-如何将实体字段映射到两个表?

-如何连接外键具有不同列名的两个表(此处CUSTOMER_ID和PERSON_ID)?

非常感谢,

PS :我知道我们可以通过制作两个带有数据注释的实体来做到这一点。我想避免数据注释(因为关注点分离)并且我想保留一个实体。

首先,您的模型看起来不对。你(可能)想要这样的东西:

public class Contract
{
    public int ContractId { get; set; }
    public int PersonId { get; set; }
    public Person Customer { get; set; }  // Use a navigation property to relate
}

public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public ICollection<Contract> Contracts { get; set; }  // A person can have many contracts, no?
}

现在您可以将流畅的代码更改为:

public class ContractConfiguration : EntityTypeConfiguration<Contract>
{
    public ContractConfiguration()
    {
        ToTable("T_CONTRACTS", "ASSUROL"); //table and schema ALWAYS in uppercase
        HasKey(c => c.ContractId);  // Redundant since ContractId is key via convention
        Property(c => c.ContractId).HasColumnName("CONTRACT_ID").IsRequired();
        Property(c => c.PersonId).HasColumnName("CUSTOMER_ID").IsRequired();

        // Configure the relationship although EF should pick this up by convention as well...
        HasRequired(c => c.Customer).WithMany(p => p.Contracts);

    }
}

现在您可以非常轻松地为 "flatten" 关系编写查询:

context.Contracts.Select(c => new {
       c.ContractId,
       CustomerId = c.PersonId,
       CustomerName = c.Person.Name }).ToList();

编辑:重读后,我发现您可能想要的是 table 拆分,尽管第一种方法在 IMO 中更好,因为看起来您正在尝试将 ViewModel 构建到您的实体模型中不是 table 分裂的意图。 IAC,如果你想要它,流畅的代码看起来类似于:

modelBuilder.Entity<Contract>() 
    .Map(m => 
    { 
        m.Properties(c => new { c.CustomerId, c.ContractId }); 
        m.ToTable("T_CONTRACTS"); 
    }) 
    .Map(m => 
    { 
        m.Properties(p => new { p.PersonID, p.Name }); 
        m.ToTable("T_PERSONS"); 
    });

https://msdn.microsoft.com/en-us/data/jj591617.aspx?f=255&MSPPError=-2147217396#2.7

非常感谢,由于关键字 "Entity Splitting",我找到了其他帖子: Entity splitting when key column has different names?

这是我的工作配置:

    public ContractConfiguration()
    {
        HasKey(c => c.CustomerId);
        Map(m =>
        {
            m.Property(c => c.ContractId).HasColumnName("CONTRACT_ID");
            m.Property(c => c.CustomerId).HasColumnName("CUSTOMER_ID");
            m.ToTable("T_CONTRACTS");
        });
        Map(m =>
        {
            m.Property(cust => cust.CustomerId).HasColumnName("PERSON_ID");
            m.Property(cust => cust.CustomerName).HasColumnName("NAME");
            m.ToTable("T_PERSONS");
        });
    }