简体   繁体   中英

Code first: One to many relationship of the same entity

I have an Entity Product which can have multiple additional products. So what I need is a junction table to map a Product to additional Product s.

What I tried to do is the following:

[Table("Product")]
public class Product : EntityBase
{
    [Key]
    public int Id { get; set; }

    public virtual ICollection<Argument> Arguments { get; set; }
    public virtual ICollection<Product> AdditionalProducts { get; set; }
}

Add a collection of Products, hoping that EF would build a junction table. However I end up with this in my migration:

public partial class test1 : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.Product", "Product_Id", c => c.Int());
        CreateIndex("dbo.Product", "Product_Id");
        AddForeignKey("dbo.Product", "Product_Id", "dbo.Product", "Id");
    }

    public override void Down()
    {
        DropForeignKey("dbo.Product", "Product_Id", "dbo.Product");
        DropIndex("dbo.Product", new[] { "Product_Id" });
        DropColumn("dbo.Product", "Product_Id");
    }
}

What am I doing wrong here?

As you said in the comment that:

A product can be an additional product to multiple products. And can also have its set of additional products.

So, First make a model class named AdditionalProduct as follows:

[Table("AdditionalProduct")]
public class AdditionalProduct
{
    [Key]
    public int Id { get; set; }

    public int ProductId {get; set;}
    public int AdditionalProductId {get; set;}

    public Product Product {get; set;}
    public Product AdditionalProduct {get; set;}
}

And your Product class should as follows:

[Table("Product")]
public class Product : EntityBase
{
    [Key]
    public int Id { get; set; }

    .......

    public virtual ICollection<AdditionalProduct> HisAdditionalProducts { get; set; }
    public virtual ICollection<AdditionalProduct> AdditionalProductsTo { get; set; }
}

Then in the OnModelCreating as follows:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<AdditionalProduct>()
                .HasRequired(m => m.Product)
                .WithMany(t => t.HisAdditionalProducts)
                .HasForeignKey(m => m.ProductId)
                .WillCascadeOnDelete(false);

    modelBuilder.Entity<AdditionalProduct>()
                .HasRequired(m => m.AdditionalProduct)
                .WithMany(t => t.AdditionalProductsTo)
                .HasForeignKey(m => m.AdditionalProductId)
                .WillCascadeOnDelete(false);
}

The great solution for you is:

First, make a new class for all your Aditional Productions

[Table("AdditionalProducts")]
public class AdditionalProduct
{
    [Key]
    public int Id { get; set; }

    public virtual ICollection<Product> AdditionalProducts { get; set; }
}

Second, create a relationship one-to-one to this class

[Table("Product")]
public class Product
{
    [Key]
    public int Id { get; set; }

    public virtual ICollection<Argument> Arguments { get; set; }//your business

    public int AdditionalProductsId { get; set; }
    public virtual AdditionalProduct AdditionalProducts { get; set; }
}

See more one-to-one

Hope to be useful for you!

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