实体框架代码优先:在具有不同连接列的实体中展平组合
Posted
技术标签:
【中文标题】实体框架代码优先:在具有不同连接列的实体中展平组合【英文标题】:Entity Framework Code First : flatten composition in entity with different join column 【发布时间】:2016-10-23 05:12:40 【问题描述】:我在使用 Code First 配置使用 EntityFramework 时遇到问题。 我有两张桌子:
+---------------+ +-------------+
| 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:我知道我们可以通过创建两个带有数据注释的实体来做到这一点。我想避免数据注释(因为关注点分离),我想保留一个实体。
【问题讨论】:
【参考方案1】:首先,您的模型看起来不正确。你(可能)想要这样的东西:
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);
现在您可以很容易地编写一个查询来“扁平化”关系:
context.Contracts.Select(c => new
c.ContractId,
CustomerId = c.PersonId,
CustomerName = c.Person.Name ).ToList();
编辑:重读后,我发现您可能需要的是表拆分,尽管第一种方法更好 IMO,因为您似乎正在尝试将 ViewModel 构建到您的实体模型中,这不是表的意图分裂。 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
【讨论】:
【参考方案2】:非常感谢,感谢关键字“实体拆分”,我找到了其他帖子: Entity splitting when key column has different names? Entity framework map entity to multiple tables?
这是我的工作配置:
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");
);
【讨论】:
以上是关于实体框架代码优先:在具有不同连接列的实体中展平组合的主要内容,如果未能解决你的问题,请参考以下文章