EF核心多对多关系设置父对象的两个关键

时间:2018-02-18 22:08:46

标签: entity-framework asp.net-core

我正在构建一个代表可以在使用EF Core 2.0编写的电子商务平台中创建的典型产品的模型。请参阅下面的模型结构

<body onload="main();">

这就是我为Fluent API设置的内容。

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; }

}

还包括迁移

           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);

脚手架/迁移工作正常,我实际上可以创建没有包含所有关系的问题的产品。当我尝试将“RelatedProduct”添加到Product模型时出现问题。

我相应地设置了ParentProductId和ChildProductId,当我创建或更新实体时,它将ParentProductId和ChildProductId值都设置为ParentProductId。

我已经通过我的调试器跟踪了代码,直到我调用_context.Update(entity)为止。之后,RelatedProduct模型中的两个ID都设置为相同的值。

我不知道为什么会这样,任何建议都会非常有用。

1 个答案:

答案 0 :(得分:0)

我认为您的迁移生成方式存在问题。从上面的代码我不确定GSRelatedProduct中的子属性的用途是什么。如果查看迁移,您将看到为父项和子项设置了相同的约束:

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);

Parent和Child都具有相同的主表和主列。它们都会从GSProducts表中获得相同的值。您的逻辑或业务流程是我无法弄清楚的,但实际上您正在获得预期的效果。孩子应该指向其他什么吗?在您的代码中,您可能正在为产品和子项分配不同的值,但这似乎以某种方式被覆盖。基本上,您的代码首先认为两者和父代都应该具有相同的值。换句话说,儿童似乎是多余的。

您的GSProduct表是一个自引用表,您可以将产品和子产品保存在一起吗?如果是这样,那么您需要一个用于此目的的附加列,例如ParentId指向Id以获得所需的关系。