Reputation:
I have the following classes:
public class InvoiceLine
{
public Guid Id { get; set; }
public int LineNumber { get; set; }
public List<ProductCode> ProductCodes { get; set; }
}
public class ProductCode
{
public string Category { get; set; }
public string Value { get; set; }
}
In the case of ProductCode
the Category
and the Value
are together the primary key.
I set this up in the DbContext
:
modelBuilder.Entity<ProductCode>()
.HasKey(pc => new { pc.Category, pc.Value });
One InvoiceLine
can have many product codes but a product code can be used for various InvoiceLine
s.
In EF Core I have to create a join entity with the ids and entitites:
public class InvoiceLineProductCode
{
public Guid InvoiceLineId { get; set; }
public InvoiceLine InvoiceLine { get; set; }
public ProductCode ProductCode { get; set; }
}
How can I set the ProductCodeId
?
Upvotes: 2
Views: 3221
Reputation: 205849
Adding composite FK is similar to adding single column FK.
Start by adding the PK column(s) of the referenced entity:
public class InvoiceLineProductCode
{
public Guid InvoiceLineId { get; set; }
public InvoiceLine InvoiceLine { get; set; }
public string ProductCodeCategory { get; set; } // <--
public string ProductCodeValue { get; set; } // <--
public ProductCode ProductCode { get; set; }
}
Then define the composite join entity PK as usual:
modelBuilder.Entity<InvoiceLineProductCode>()
.HasKey(e => new { e.InvoiceLineId, e.ProductCodeCategory, e.ProductCodeValue });
Also don't forget to change the Invoice
collection navigation property type:
public class InvoiceLine
{
public Guid Id { get; set; }
public int LineNumber { get; set; }
public List<InvoiceLineProductCode> ProductCodes { get; set; } // <--
}
and since the names match EF Core conventions, you are done. In cases they don't, the full configuration of the relationship ProductCode
-> InvoiceLineProductCode
would be like this:
modelBuilder.Entity<InvoiceLineProductCode>()
.HasOne(e => e.ProductCode)
.WithMany()
.HasForeignKey(e => new { e.ProductCodeCategory, e.ProductCodeValue })
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
Upvotes: 4