简体   繁体   中英

Entity Framework - Code First / Fluent API - Filtered navigation properties

I am trying to define the relationships of the following three classes with the code first approach and the fluent API, but I am reaching a dead end.

Given the following three classes:

public class Contract {
  public Contract {
    this.PaymentRequests = new HashSet<PaymentRequest>();
    this.Bills = new HashSet<Bill>();
  }

  public long Id { get; set; }
  public virtual ICollection<PaymentRequest> PaymentRequests { get; set; }
  public virtual ICollection<Bill> Bills { get; set; }
}

public class Bill {
  public Bill {
    this.PaymentRequests = new HashSet<PaymentRequest>();
  }

  public long Id { get; set; }
  public virtual Contract Contract { get; set; }
  public virtual ICollection<PaymentRequest> PaymentRequests { get; set }
}

public class PaymentRequest {
  public long Id { get; set; }
  public virtual Contract Contract { get; set; }
  public virtual Bill Bill { get; set; }
}

I want to define the relationship in the following way: A contract maintains a list of PaymentRequests which do not have a Bill set yet and a list of bills that contains a list of PaymentRequests with the Bill set to the current bill.

Therefore I am trying to setup the mappings accordingly:

public class ContractMap : EntityTypeConfiguration<Contract> {
  public ContractMap() {
    this.HasKey(x => x.Id);

    this.HasMany(x => x.PaymentRequests)
        .WithRequired(pr => pr.Contract);
    this.HasMany(x => x.Bills)
        .WithRequired(b => b.Contract);
  }
}

public class BillMap : EntityTypeConfiguration<Bill> {
  public BillMap() {
    this.HasKey(x => x.Id);

    this.HasRequired(x => x.Contract);
    this.HasMany(x => x.PaymentRequests)
        .WithRequired(x => x.Bill);
  }
}

public class PaymentRequestMap : EntityTypeConfiguration<PaymentRequest> {
  public PaymentRequestMap() {
    this.HasKey(x => x.Id);

    this.HasRequired(x => x.Contract);
    this.HasOptional(x => x.Bill);
  }
}

But this does not really work. Is it possible at all to define such relationships or would I need to create another member which is for instance called OpenPaymentRequests and tell the EF to ignore it and then populate it in (eg) a repository and do the same for the PaymentRequests in a Bill? I am not able to find anything like that online to get some useful information of the best-practice way to solve something like the above. Any input is very welcome and appreciated!

You're configuring PaymentRequests to require both a Bill and a Contract via your ContractMap and BillMap classes. For your purposes, PaymentRequest should only require a Contract - Bill should be optional (as you chose to do in your PaymentRequestMap class, which is actually not needed due to the previous two configuration classes)

public class ContractMap : EntityTypeConfiguration<Contract> {
  public ContractMap() {
    this.HasKey(x => x.Id);

    this.HasMany(x => x.PaymentRequests)
        .WithRequired(pr => pr.Contract);
    this.HasMany(x => x.Bills)
        .WithRequired(b => b.Contract);
  }
}

public class BillMap : EntityTypeConfiguration<Bill> {
  public BillMap() {
    this.HasKey(x => x.Id);

    this.HasRequired(x => x.Contract);
    this.HasMany(x => x.PaymentRequests)
        // change this to .WithOptional( x => x.Bill )
        .WithOptional(x => x.Bill);
  }
}

public class PaymentRequestMap : EntityTypeConfiguration<PaymentRequest> {
  public PaymentRequestMap() {
    this.HasKey(x => x.Id);

    this.HasRequired(x => x.Contract);
    this.HasOptional(x => x.Bill);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM