我有一个现有的数据库,我试图通过Entity Framework 4.3访问。大多数表格和关系都不是问题,但是这组表格给我带来了一些我似乎无法找到答案的问题。
以下是(简明)实体:
客户
public class Customer
{
public int CustomerID { get; set; }
public string Name { get; set; }
private int addressSourceTypeID = 2;
[NotMapped]
public int AddressSourceTypeID {
get { return addressSourceTypeID; }
set { addressSourceTypeID = value; } }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
合同
public class Contract
{
public int ContractID { get; set; }
public string Name { get; set; }
private int addressSourceTypeID = 4;
[NotMapped]
public int AddressSourceTypeID {
get { return addressSourceTypeID; }
set { addressSourceTypeID = value; } }
public virtual int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
//public virtual ICollection<Address> Addresses { get; set; }
}
地址
public class Address
{
[Key]
public int AddressID { get; set; }
public int AddressSourceTypeID { get; set; }
[ForeignKey("Customer")]
public int SourceKey { get; set; }
public virtual Customer Customer { get; set; }
//public virtual Contract Contract { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
我上面提到的是两个实体Customer
和Contract
,它们都可以包含子Address
个实体。目前,Address
实体已设置为Customer
实体的子级,但由于Contract
没有指向Address
的链接,因此效果很好。
我已尝试将Contract
添加到Address
实体,就像我对Customer
实体所做的那样,您可以从注释掉的代码段中看到。不幸的是,这不起作用,但由于在Customer
ForeignKey注释中引用了Address
,我并不感到惊讶。我甚至尝试创建Address
实体的特定版本(即CustomerAddress
),但是当多个实体尝试绑定到同一个表时,我收到错误。
我也尝试在EF ModelBuilder
中使用DBContext
但是我的知识非常有限,我不知道在这种情况下如何做。
总的来说,我需要的是以下内容:
这些“父”表与地址表之间的链接使用以下内容:
如果有人能帮助我,或指出我的方向正确,那就太好了。
非常感谢。
答案 0 :(得分:2)
您可以让EF使用每个层次结构继承表强制执行SourceKey
属性 - 然后您的映射将中断,或者您可以在业务逻辑中强制执行SourceKey
并且只有EF管理主Address
类。
如果您必须维护当前的数据库架构,我认为让您的业务逻辑强制执行您的SourceKey
作为分歧者是您唯一的选择:
public class Address
{
public int AddressID { get; set; }
public int AddressSourceTypeID { get; set; }
public int SourceKey { get; set; }
public virtual Contract Contract { get; set; }
public virtual Customer Customer { get; set; }
}
public class Contract
{
public Contract()
{
this.Addresses = new List<Address>();
}
public int ContractID { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Customer
{
public Customer()
{
this.Addresses = new List<Address>();
}
public int CustomerID { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
这是你流利的映射:
modelBuilder.Entity<Address>().HasOptional(t => t.Contract)
.WithMany(t => t.Addresses)
.HasForeignKey(d => d.SourceKey);
modelBuilder.Entity<Address>().HasOptional(t => t.Customer)
.WithMany(t => t.Addresses)
.HasForeignKey(d => d.SourceKey);
或者 - 如果您创建了CustomerAddress
和ContractAddress
,则可以使用TPH继承强制执行SourceKey
- 但目前无法映射导航属性:
public abstract class Address
{
[Key]
public int AddressID { get; set; }
public int AddressSourceTypeID { get; set; }
public int SourceKey { get; set; }
}
public class CustomerAddress : Address
{
public virtual Customer Customer { get; set; }
}
public class ContractAddress : Address
{
public virtual Contract Contract { get; set; }
}
这是你的映射:
modelBuilder.Entity<Address>()
.Map<ContractAddress>(m => m.Requires("AddressSourceTypeID").HasValue(2))
.Map<CustomerAddress>(m => m.Requires("AddressSourceTypeID").HasValue(4));
这将强制AddressSourceTypeID
作为您的鉴别者 - 遗憾的是,此处的细分是将您的导航属性映射回ContractAddress和客户地址。请参阅具有相同基本问题的this related post。也许这会让你开始朝着正确的方向前进。