简体   繁体   中英

Entity Framework Code First Two navigationProperty to/from one abstract entity

The following entities is my code first which PersonParameter is an abstract class and Shirt and Shoes are inherited from it with typ(1,2)

[Table("Person")]
public class Person
{
    [Key]
    public int id { get; set; }
    public string Name { get; set; }

    public int? shirtID { get; set; }
    public int? shoesID { get; set; }

    [ForeignKey("shirtID")]
    public Shirt Shirt { get; set; }
    [ForeignKey("shoesID")]
    public Shoes Shoes { get; set; }
}

[Table("PersonParameter")]
public abstract class PersonParameter
{
    public int id { get; set; }
    public string Title { get; set; }
    public string Value { get; set; }

    public List<Person> Persons { get; set; }
}

public class Shirt : PersonParameter
{

}
public class Shoes : PersonParameter
{

}

and for model dbcontext

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<PersonParameter>()
        .Map<Shirt>(p => p.Requires("typ").HasValue(1))
        .Map<Shoes>(p => p.Requires("typ").HasValue(2));
}

but the above codes will create unwanted field PersonParameter_id in Person table:

public override void Up()
{
    CreateTable(
        "dbo.PersonParameter",
        c => new
            {
                id = c.Int(nullable: false, identity: true),
                Title = c.String(),
                Value = c.String(),
                typ = c.Int(nullable: false),
            })
        .PrimaryKey(t => t.id);

    CreateTable(
        "dbo.Person",
        c => new
            {
                id = c.Int(nullable: false, identity: true),
                Name = c.String(),
                shirtID = c.Int(),
                shoesID = c.Int(),
                PersonParameter_id = c.Int(),
            })
        .PrimaryKey(t => t.id)
        .ForeignKey("dbo.PersonParameter", t => t.shirtID)
        .ForeignKey("dbo.PersonParameter", t => t.shoesID)
        .ForeignKey("dbo.PersonParameter", t => t.PersonParameter_id)
        .Index(t => t.shirtID)
        .Index(t => t.shoesID)
        .Index(t => t.PersonParameter_id);

}

how can I solve it (PersonParameter_id) I did some FluentApi with HasOptional.WithMany but didn't solve.

EDIT
After some test, found that for non abstract class it create extra id too and the one solution for fixing that issue is removing navigation property from parameter class and adding it to the inheritance classes (shirt and shoes)

The reason you end up with one additional FK on Persons table is because of the Persons property on PersonParameter class. Basically EF cannot relate that to any of the current two relationships defined (Shirt and Shoes) and figured that Persons property must have been a third relationship between Persons and PersonParamter tables and therefore creates a third FK (PersonParameter_id) to create this relationship. As a result, you end up with 3 uni-directional Many to One relationships from PersonParameter to Persons.

To fix this, you need to explicitly tell EF that Persons is in fact the Inverse Property of Shoes and Shirts since there is no way that EF can pick that up automatically. You can do that with fluent API or by Annotations like this:

[Table("PersonParameter")]
public abstract class PersonParameter
{
    public int id { get; set; }
    public string Title { get; set; }
    public string Value { get; set; }
}

public class Shirt : PersonParameter
{
    [InverseProperty("Shirt")]
    public List<Person> Persons { get; set; }
}

public class Shoes : PersonParameter
{
    [InverseProperty("Shoes")]
    public List<Person> Persons { get; set; }
}


You can also achieve this by using the Fluent API:

modelBuilder.Entity<Shirt>()
    .HasMany(s => s.Persons)
    .WithOptional(p => p.Shirt)
    .HasForeignKey(p => p.shirtID);

modelBuilder.Entity<Shoes>()
    .HasMany(s => s.Persons)
    .WithOptional(p => p.Shoes)
    .HasForeignKey(p => p.shoesID);

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