2016-12-06 48 views
1

給出以下粗略的代碼優先模式,目標看起來很簡單。 Invoice可以來自或來自Company,並且Invoices收集應包含所有發票,而不管它是哪個。2個外鍵,1個導航屬性,通過兩個

public class Company 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Invoice> Invoices { get; set; } 
} 

public class Invoice 
{ 
    public int Id { get; set; } 
    public int FromCompanyId { get; set; } 
    public int ToCompanyId { get; set; } 
    public virtual Company FromCompany { get; set; } 
    public virtual Company ToCompany { get; set; } 
} 

你會在遷移注意,第三Company_Id產生的原因很明顯,支持Invoices導航屬性爲EF只有出現支持1導航道具 - > 1 FK安排。

我的問題是,是否有可能有Invoices屬性同時包含,或者我是否應該單獨把它們映射(即IC<Inv> InvoicesFromIC<Inv> InvoicesTo),並創建一個客戶端收集到兩個必須手動。

我曾嘗試:

  1. 在兩個FromCompanyToCompany,其迷惑EF,因爲它不能確定關係的主端使用InverseProperty

    [ForeignKey(nameof(FromCompanyId)), InverseProperty(nameof(Company.Invoices))] 
    public virtual Company FromCompany { get; set; } 
    [ForeignKey(nameof(ToCompanyId)), InverseProperty(nameof(Company.Invoices))] 
    public virtual Company ToCompany { get; set; } 
    
  2. 使用流利API來映射他們,但它僅考慮第二這是有意義的,從代碼的角度。

    modelBuilder.Entity<Company>() 
         .HasMany(m => m.Invoices) 
         .WithRequired(m => m.ToCompany) 
         .WillCascadeOnDelete(false); 
        modelBuilder.Entity<Company>() 
         .HasMany(m => m.Invoices) 
         .WithRequired(m => m.FromCompany) 
         .WillCascadeOnDelete(false); 
    

當然沒有什麼大問題,如果這是不可能的,我只是敢發誓我以前做過。

回答

0

對於後人來說,這裏是一個完整版本的解決方案,用於維護公司的IEnumerable<Invoices>,該公司包含兩個集合。

public class MyContext : DbContext 
{ 
    public MyContext() : base("DefaultConnection") { } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<Company>().HasMany(c => c.InvoicesFrom).WithRequired(i => i.FromCompany).WillCascadeOnDelete(false); 
     modelBuilder.Entity<Company>().HasMany(c => c.InvoicesTo).WithRequired(i => i.ToCompany).WillCascadeOnDelete(false); 
    } 

    public DbSet<Company> Companies { get; set; } 
    public DbSet<Invoice> Invoices { get; set; } 
} 

public class Company 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Invoice> InvoicesFrom { get; set; } 
    public virtual ICollection<Invoice> InvoicesTo { get; set; } 

    [NotMapped] 
    public IEnumerable<Invoice> Invoices 
    { 
     get { 
      return InvoicesFrom.Union(InvoicesTo); 
     } 
    } 
} 

public class Invoice 
{ 
    public int Id { get; set; } 
    public int FromCompanyId { get; set; } 
    public int ToCompanyId { get; set; } 
    public virtual Company FromCompany { get; set; } 
    public virtual Company ToCompany { get; set; } 
}