Entity Framework Code First Two navigationProperty в / из одного абстрактного объекта
Следующие сущности - это мой первый код, PersonParameter - абстрактный класс, и Shirt и Shoes наследуются от него с помощью 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
{
}
и для модели 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));
}
но приведенные выше коды создадут нежелательное поле PersonParameter_id в таблице Person:
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);
}
Как я могу решить эту проблему (PersonParameter_id) Я сделал некоторые FluentApi с HasOptional.WithMany, но не решил.
РЕДАКТИРОВАТЬ
После некоторого теста выяснилось, что для неабстрактного класса также создается дополнительный идентификатор, и единственным решением для устранения этой проблемы является удаление свойства навигации из класса параметров и добавление его в классы наследования (рубашка и обувь)
1 ответ
Причина, по которой вы получаете одну дополнительную FK для таблицы Persons, заключается в свойстве Persons класса PersonParameter. По сути, EF не может связать это ни с одним из двух текущих отношений, определенных (Shirt и Shoes) и полагать, что свойство Persons должно быть третьим отношением между таблицами Persons и PersonParamter, и поэтому создает третий FK (PersonParameter_id) для создания этого отношения. В результате вы получаете 3 однонаправленных отношения "многие к одному" от PersonParameter к Persons.
Чтобы это исправить, вам нужно явно сказать EF, что Persons на самом деле является обратным свойством обуви и рубашек, поскольку EF не может подобрать это автоматически. Вы можете сделать это с помощью свободно распространяемого 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; }
}
Вы также можете достичь этого, используя 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);