实体框架:许多关系中的继承不检索结果

时间:2015-06-04 22:56:22

标签: c# .net entity-framework

对于人为的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.TraitsDog.DogTraits集合为NULL。

我可以理解EF是否需要一些帮助来确定如何正确填充这些集合。同样值得注意的是,即使他是一只狗,实际上还有CatTrait与Fido相关联。我甚至会期望抛出异常,或者其他一些错误。但是要让Find操作成功,返回一个Pet,但是默默地将集合留空是我不理解的。

问题:如何设置模型以便填充这些集合?我希望DogTraits中有一个条目,Traits有3条(即使它们不是所有DogTraits)。

1 个答案:

答案 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

其次,我非常肯定在定义基类型之间的关系时,不能在继承类型中使用属性。

以下是一些可能有助于您获得所需内容的建议:

  1. 将派生类型的集合属性转换为执行过滤的getter(如果已完成以下验证,则基本上进行转换)。

    public class DogTrait : PetTrait
    {
        public IEnumerable<Dog> DogsWithTrait 
        { 
            get { return PetsWithTrait.OfType<Dog>(); } 
        }
    }
    
  2. 使用验证确保Dog只有DogTrait个,CatCatTrait等。