C# 实体框架代码前两个navigationProperty与一个抽象实体之间的转换

C# 实体框架代码前两个navigationProperty与一个抽象实体之间的转换,c#,entity-framework,abstract-data-type,tph,C#,Entity Framework,Abstract Data Type,Tph,下面的实体是我的代码,PersonParameter是一个抽象类,Shirt和Shoes是用typ(1,2)从中继承的 如何解决它(PersonParameter\u id) 我用HasOptional.WithMany做了一些FluentApi,但没有解决 编辑 经过一些测试,发现对于非抽象类,它也会创建额外的id,解决这个问题的一个解决方案是从参数类中删除导航属性,并将其添加到继承类(shirt和shoes)之所以在Persons表上增加一个FK,是因为PersonParameter类上的P

下面的实体是我的代码,PersonParameter是一个抽象类,Shirt和Shoes是用typ(1,2)从中继承的

如何解决它(PersonParameter\u id) 我用HasOptional.WithMany做了一些FluentApi,但没有解决

编辑

经过一些测试,发现对于非抽象类,它也会创建额外的id,解决这个问题的一个解决方案是从参数类中删除导航属性,并将其添加到继承类(shirt和shoes)

之所以在Persons表上增加一个FK,是因为PersonParameter类上的Persons属性。基本上,EF无法将其与当前定义的两个关系(衬衫和鞋子)中的任何一个联系起来,并且认为Persons属性必须是Persons和PersonParameter表之间的第三个关系,因此创建第三个FK(PersonParameter_id)来创建此关系。因此,最终会得到从PersonParameter到Persons的3个单向多对一关系

要解决这个问题,您需要明确地告诉EF,人实际上是鞋子和衬衫的反向属性,因为EF无法自动拾取这一属性。您可以使用fluent API或通过如下注释来实现:

[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; }
}
[表(“PersonParameter”)]
公共抽象类PersonParameter
{
公共int id{get;set;}
公共字符串标题{get;set;}
公共字符串值{get;set;}
}
公共类衬衫:PersonParameter
{
[反向属性(“衬衫”)]
公共列表人员{get;set;}
}
公共类鞋:PersonParameter
{
[反向属性(“鞋”)]
公共列表人员{get;set;}
}

您也可以通过使用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);
modelBuilder.Entity()
.有许多人(s=>s.人)
.可选(p=>p.Shirt)
.HasForeignKey(p=>p.shirtID);
modelBuilder.Entity()
.有许多人(s=>s.人)
.可选(p=>p.Shoes)
.HasForeignKey(p=>p.shoesID);

但是PersonParameter有两个FK(ShirtID和ShoesID),所以为什么需要额外的FK?谢谢您的评论。我相应地更新了我的答案。谢谢。我以前做过,但重要的是在主类(PersonParameter)中有导航属性,而不是在其继承类中,因为它应该是一个基本类。另外,我还有一些用于声明公共列表人员{get;set;}的测试作为一个抽象属性,我相信有一个使用Fluent API的解决方案可以告诉ef这些反向属性。我用Fluent API更新了我的答案,但不幸的是,我不认为有一种方法可以让ef在基类中拥有Persons属性,并为每个子类定义两种不同的关系。
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);

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