对于人为的POCO实体示例:
public class Pet
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<PetTrait> Traits { get; set; }
}
public class Dog : Pet
{
public ICollection<DogTrait> DogTraits { get; set; }
}
public class SmallDog : Dog { }
public class LargeDog : Dog { }
public class Cat : Pet
{
public ICollection<CatTrait> CatTraits { get; set; }
}
public class PetTrait
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Pet> PetsWithTrait { get; set; }
}
public class DogTrait : PetTrait
{
public ICollection<Dog> DogsWithTrait { get; set; }
}
public class CatTrait : PetTrait
{
public ICollection<Cat> CatsWithTrait { get; set; }
}
......实体框架6对我很好。我还没有需要对模型构建器做任何事情。创建的表格如下:
Pets
Id Name Discriminator
1 Fido SmallDog
PetTraits
Id Name Discriminator
1 Smart DogTrait
2 Furry CatTrait
3 Alive PetTrait
PetTraitPets
PetTrait_Id Pet_Id
1 1
2 1
3 1
如果我在宠物的身份证上执行查找操作
using (var db = new DbPets()) var pet = db.Pets.Find(1);
EF让我Fido。正如预期的那样,pet.GetType()
会返回SmallDog
。但是,Pet.Traits
和Dog.DogTraits
集合为NULL。
我可以理解EF是否需要一些帮助来确定如何正确填充这些集合。同样值得注意的是,即使他是一只狗,实际上还有CatTrait
与Fido相关联。我甚至会期望抛出异常,或者其他一些错误。但是要让Find操作成功,返回一个Pet,但是默默地将集合留空是我不理解的。
问题:如何设置模型以便填充这些集合?我希望DogTraits
中有一个条目,Traits
有3条(即使它们不是所有DogTraits)。
答案 0 :(得分:1)
首先,您需要将virtual
添加到您的集合属性,使用db.Pets.Include(p => p.Traits)
的查询,或使用db.Entry(pet).Collection(p => p.Traits).Load()
,以便在您访问时可以使用相关对象属性。 (见https://msdn.microsoft.com/en-us/data/jj574232.aspx)
其次,我非常肯定在定义基类型之间的关系时,不能在继承类型中使用属性。
以下是一些可能有助于您获得所需内容的建议:
将派生类型的集合属性转换为执行过滤的getter(如果已完成以下验证,则基本上进行转换)。
public class DogTrait : PetTrait
{
public IEnumerable<Dog> DogsWithTrait
{
get { return PetsWithTrait.OfType<Dog>(); }
}
}
使用验证确保Dog
只有DogTrait
个,Cat
有CatTrait
等。