2016-12-06 67 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; } 
}