2012-09-21 99 views
0

我有一個現有的數據庫,我試圖通過實體框架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; } 
} 

我上面的是兩個實體CustomerContract,這兩個實體都可以有子女Address。目前,Address實體被設置爲Customer實體的子項,並且此工作正常,因爲沒有從AddressContract的鏈接。

我曾嘗試在中加入Address實體,就像我在Customer實體中所做的那樣,您可以從註釋掉的代碼段中看到。不幸的是,這不起作用,但我並不感到驚訝,因爲在Address ForeignKey註釋中引用Customer。我甚至試圖創建Address實體的特定版本(即CustomerAddress),但是當多個實體試圖綁定到同一個表時,我得到一個錯誤。

我也嘗試在EF DBContext中使用ModelBuilder但是我在這裏的知識是相當有限的,我不知道在這種情況下如何做到這一點。

總體來說,我需要的是以下幾點:

  • 客戶實體有子地址的集合。
  • 要收集子地址的合同實體。

到地址表中的這些 '父' 表之間的鏈路使用以下:

  • 顧客:客戶id =>地址:SourceKey和客戶:AddressSourceTypeID(始終爲2)=>地址:AddressSourceTypeID。
  • 合同:ContractID =>地址:SourceKey AND合同:AddressSourceTypeID(始終爲4)=>地址:AddressSourceTypeID。

如果任何人都可以幫助我,或者指出我會朝着正確的方向發展。

非常感謝。

+0

數據庫中的Address表中的SourceKey列是* both *一對多關係的外鍵???這在技術上是允許的,您可以在'SourceKey'上使用兩個'[ForeignKey]'註釋來表示'Customer'和'Contract'導航屬性。但是,這意味着無論何時,通過'SourceKey' FK'Address'引用'Customer''1234'時,還必須有'Contract'1234',反之亦然 - 這很難想象,因爲'Customer'和'契約'通過一對多關係相關,您的密鑰看起來像自動生成的身份。 – Slauma

回答

2

您可以有EF每一個分層繼承執行你的SourceKey屬性利用表 - 然後你映射將打破,或者你可以在你的業務邏輯執行SourceKey,只有有EF管理主要Address類。

如果維持目前的DB模式,我認爲有你的業務邏輯執行你的SourceKey作爲disriminator是你唯一的選擇:

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

或者 - 如果您創建了CustomerAddressContractAddress,則可以使用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,它們具有相同的基本問題。也許這會讓你至少在正確的方向開始。

+0

工作幾乎100%,唯一的問題是我需要使'SourceKey'爲空。非常感謝。 – XN16