I working on building out a model that would represent a typical product that could be created in an e-commerce platform written using EF Core 2.0. See the model structure below
public class GSProduct : BaseEntity
{
[Required]
public string Name { get; set; }
public ICollection<GSProduct> BaseProducts { get; set; }
public ICollection<GSRelatedProduct> ParentProducts { get; set; }
public ICollection<GSRelatedProduct> ChildProducts { get; set; }
public ICollection<GSVendorProductInfo> VendorProductInfo { get; } = new List<GSVendorProductInfo>();
}
public class GSRelatedProduct
{
public virtual GSProduct ParentProduct { get; set; }
public Guid ParentProductId { get; set; }
public virtual GSProduct ChildProduct { get; set; }
public Guid ChildProductId { get; set; }
}
public class GSVendorProductInfo : BaseEntity
{
public GSContact Vendor { get; set; }
public Guid VendorId { get; set; }
public GSProduct Product { get; set; }
public Guid ProductId { get; set; }
public string VendorPartNumber { get; set; }
public int BaseUnits { get; set; }
public double Cost { get; set; }
public int MinOrderQty { get; set; }
public int OrderedInMultiples { get; set; }
}
This is what I have set up for the Fluent API.
modelBuilder.Entity<GSVendorProductInfo>()
.HasOne(pt => pt.Product)
.WithMany(p => p.VendorProductInfo)
.HasForeignKey(pt => pt.ProductId);
modelBuilder.Entity<GSVendorProductInfo>()
.HasOne(pt => pt.Vendor)
.WithMany(t => t.VendorProductInfo)
.HasForeignKey(pt => pt.VendorId);
modelBuilder.Entity<GSRelatedProduct>().HasKey(x => new { x.ParentProductId, x.ChildProductId });
modelBuilder.Entity<GSRelatedProduct>()
.HasOne(pt => pt.ParentProduct)
.WithMany(t => t.ParentProducts)
.HasForeignKey(pt => pt.ParentProductId);
modelBuilder.Entity<GSRelatedProduct>()
.HasOne(pt => pt.ChildProduct)
.WithMany(t => t.ChildProducts)
.HasForeignKey(pt => pt.ChildProductId);
Also including the migration
migrationBuilder.CreateTable(
name: "GSRelatedProducts",
columns: table => new
{
ParentProductId = table.Column<Guid>(nullable: false),
ChildProductId = table.Column<Guid>(nullable: false),
Optional = table.Column<bool>(nullable: false),
Quantity = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GSRelatedProducts", x => new { x.ParentProductId, x.ChildProductId });
table.ForeignKey(
name: "FK_GSRelatedProducts_GSProducts_ChildProductId",
column: x => x.ChildProductId,
principalTable: "GSProducts",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
table.ForeignKey(
name: "FK_GSRelatedProducts_GSProducts_ParentProductId",
column: x => x.ParentProductId,
principalTable: "GSProducts",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
});
The scaffolding / migration is working fine and I can actually create products without a problem that include all of the relationships. The issue arises when I try to add a 'RelatedProduct' to the Product model.
I set the ParentProductId and the ChildProductId accordingly and when I create or update the entity it sets both the ParentProductId and the ChildProductId value to the ParentProductId.
I've followed the code through my debugger and it is correct up until the point where I call _context.Update(entity). After that both of the Ids in the RelatedProduct model are set to the same value.
I've got no idea why this is happening any suggestions would be very helpful.