[英]Entity framework map entity to multiple tables in cascade
I'm facing a problem using EF. 我在使用EF时遇到问题。 I have the following situation:
我有以下情况:
From this database schema i'd like to generate the following entity by merge tables data: 我想从此数据库架构中通过合并表数据生成以下实体:
// Purchases
public class Purchase
{
//Fields related to Purchases
public int IdPurchase { get; set; }
public string CodPurchase { get; set; }
public int IdCustomer { get; set; }
public decimal Total { get; set; }
//Fields related to Customers table
public string CodCustomer { get; protected set; }
public string CompanyTitle { get; protected set; }
public string CodType { get; protected set; }
//Fields related to CustomersType table
public string DescrType { get; protected set; }
}
As you can see, in my context i don't want 3 separated entities for each table. 如您所见,在我的上下文中,我不希望每个表具有3个分离的实体。 I want a single one with the fields related to all tables.
我想要一个与所有表相关的字段。 All fields of Customers and CustomersType tables must be readonly (so i've set the relative setters protected) and the others must be editables so that EF can track changes.
客户表和客户类型表的所有字段都必须是只读的(因此我已将相对设置器设置为受保护的),其他字段必须是可编辑的,以便EF可以跟踪更改。 In particular, i'd like to have the ability to change the "IdCustomer" field and let EF to automatically update "CodCustomer", "CompanyTitle", "DescrType"....and so on by doing cross table select.
特别是,我希望能够更改“ IdCustomer”字段,并让EF通过执行交叉表选择来自动更新“ CodCustomer”,“ CompanyTitle”,“ DescrType” ...等等。
To do that, i wrote this configuration class: 为此,我编写了以下配置类:
internal class PurchaseConfiguration : EntityTypeConfiguration<Purchase>
{
public PurchaseConfiguration(string schema = "dbo")
{
ToTable(schema + ".Purchases");
HasKey(x => x.IdPurchase);
Property(x => x.IdPurchase).HasColumnName("IdPurchase").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.IdCustomer).HasColumnName("IdCustomer").IsRequired();
Property(x => x.Total).HasColumnName("Total").IsRequired().HasPrecision(19, 4);
Map(mc =>
{
mc.Properties(n => new
{
n.CodCustomer,
n.CompanyTitle,
n.CodType
});
mc.ToTable("Customers");
});
Map(mc =>
{
mc.Properties(n => new
{
n.DescrType,
});
mc.ToTable("CustomersType");
});
}
}
I've tested it but it doesn't work as expected. 我已经对其进行了测试,但是无法正常工作。 I always get this message:
我总是收到此消息:
Properties for type 'Purchase' can only be mapped once.
“购买”类型的属性只能映射一次。 The non-key property 'CodCustomer' is mapped more than once.
非关键属性“ CodCustomer”被映射多次。 Ensure the Properties method specifies each non-key property only once.
确保“属性”方法仅指定每个非关键属性一次。
Maybe there's something wrong or i forget something (for example the join fields of Map<> that i don't know where to specify them). 也许出了点问题,或者我忘记了一些东西(例如,我不知道在哪里指定的Map <>的联接字段)。 How can i accomplish in the correct way this task?
我如何正确完成此任务? I don't want to have "Customers" and "CustomersType" DBSets in my context.
我不想在上下文中包含“ Customers”和“ CustomersType” DBSet。 Is there a way to avoid it?
有办法避免吗?
I even thought to add into the "IdCustomer" setter a custom query to update manually "Customers" and "CustomersType" related fields, but i don't want to do that for 2 reasons: 我什至考虑将自定义查询添加到“ IdCustomer” setter中,以手动更新“ Customers”和“ CustomersType”相关字段,但是由于两个原因,我不想这样做:
I've uploaded the example C# source and the tables CREATE scripts (MS SQLServer) here . 我在此处上传了示例C#源代码和表CREATE脚本(MS SQLServer)。 All entities are autogenerated by the "EF reverse POCO generator" T4 template (the T4 template is disabled, to activate it set CustomTool = TextTemplatingFileGenerator).
所有实体均由“ EF反向POCO生成器” T4模板自动生成(禁用T4模板,可通过设置CustomTool = TextTemplatingFileGenerator来激活它)。 Do not forget to update the ConnectionString in the app.config.
不要忘记在app.config中更新ConnectionString。
Thanks in advance. 提前致谢。
I'm afraid the bad news is that this mapping is not possible with this table structure. 恐怕坏消息是此表结构无法实现此映射。 What you're trying to achieve here is known as entity splitting .
您要在此处实现的目标称为实体拆分 。 However, entity splitting requires 1:1 associations, because sets of records in the involved tables represent one entity.
但是,实体拆分需要1:1关联,因为所涉及表中的记录集代表一个实体。 With this mapping, you can't have a
Customer
belonging to more than one Purchase
. 使用此映射,您不能拥有一个
Customer
属于多个Purchase
。 That would mean that you could modify multiple Purchase
entities by modifying a Customer
property of only one of them. 这意味着您可以通过仅修改其中一个的“
Customer
属性来修改多个“ Purchase
实体。
Maybe the news isn't that bad, because I think you actually want to have 1-n associations. 也许这个消息并不是那么糟糕,因为我认为您实际上想拥有1-n关联。 But then you can't have these "flattened" properties in
Purchase
. 但是,那么在
Purchase
就不能拥有这些“扁平化”的属性。
As an alternative you could create delegated properties like so: 另外,您可以创建委托属性,如下所示:
public string CodCustomer
{
get { return this.Customer.CodCustomer; }
set { this.Customer.CodCustomer = value; }
}
You'd have to Include()
Customer
s and CustomersType
s when you fetch Purchase
s. 在获取
Purchase
时,必须Include()
Customer
和CustomersType
。
Another alternative is to use a tool like AutoMapper to map Purchase
to a DTO type having the flattened properties. 另一种选择是使用诸如AutoMapper的工具将
Purchase
映射到具有扁平属性的DTO类型。
You map the Purchase
entity to the Purchases
table. 您将
Purchase
实体映射到Purchases
表。 But you don't specify which properties you want to map to this table. 但是,您没有指定要映射到该表的属性。 So EF assumes that all properties should be mapped to it.
因此,EF假定所有属性都应映射到它。 So that's the first (implicit) mapping of
CodCustomer
. 这就是
CodCustomer
的第一个(隐式)映射。 The second one is the one in the mc.ToTable
statement. 第二个是
mc.ToTable
语句中的一个。 (EF only reports the first problem.) (EF仅报告第一个问题。)
To fix this, you should add a mapping statement for the left-over Purchase
properties: 要解决此问题,您应该为剩余的
Purchase
属性添加一个映射语句:
Map(mc =>
{
mc.Properties(n => new
{
n.IdPurchase,
n.CodPurchase,
n.IdCustomer,
n.Total,
});
mc.ToTable("Purchases");
});
By the way, you should also remove the mapping configuration classes of Customer
and CustomersType
, they're redundant. 顺便说一句,您还应该删除
Customer
和CustomersType
的映射配置类,它们是多余的。
But, as said, the database schema doesn't match the required structure. 但是,如上所述,数据库架构与所需的结构不匹配。 If you try to save a
Purchase
you will get a foreign key constraint exception. 如果您尝试保存
Purchase
,则将获得外键约束异常。 This is because EF expects the following table structure: 这是因为EF期望以下表结构:
Where the columns IdPurchase
in Customer
and CustomersType
are both primary key and foreign key to Purchase
. 其中列
IdPurchase
在Customer
和CustomersType
都是主键和外键Purchase
。 I don't think this is what you had in mind when designing the database. 我认为这不是您在设计数据库时想到的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.