在EF 4.2 POCO中从数据库中检索时,为什么我的导航属性为null?

时间:2012-01-26 21:00:04

标签: c# .net entity-framework poco

我有一个非常简单的数据模型(如下)。我无法弄清楚如何从数据库中加载导航属性。我没有遇到麻烦,但导航属性不会被EF设置。我已经看到了几个相关的问题,但它们略有不同或相关。我正在寻找有关EF 4.2(POCO)如何处理导航属性的信息。在我已经完成的阅读中,我得到的印象是我可以使用导航属性访问具有外键的对象。相反,我的属性将返回null或空,具体取决于我是否在构造函数中实例化我的集合。

public class AnimalDb : DbContext
{
    public static AnimalDb Create(string fileName)
    {
        Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
        return new AnimalDb(fileName);
    }

    private AnimalDb(string fileName) : base(fileName) { }

    public DbSet<Animal> Animals { get; set; }
}

public class Animal
{
    public Animal()
    {
        Id = Guid.NewGuid();
        Traits = new ObservableCollection<Trait>();
    }

    public Guid Id { get; set; }
    public string Species { get; set; }
    public string Name { get; set; }
    public ObservableCollection<Trait> Traits { get; set; }
}

public class Trait
{
    public Trait()
    {
        Id = Guid.NewGuid();
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
}

以下是使用它的一些(简单)代码:

foreach (var animal in db.Animals)
{
    foreach (var trait in animal.Traits)
    {
        //animal.Traits count is 0, so this does not run.
        //However there are traits in the database, as my populate
        //function is working fine.
        Console.WriteLine("{0} is {1}", animal.Name, trait.Name);
    }
}

----编辑答案摘要----

使用下面答案中提供的文章和信息,我发现我可以急切地使用db.Animals.Include()加载或启用延迟加载。有一个技巧可以启用延迟加载并能够使用它。首先启用延迟加载我添加了:

db.Configuration.LazyLoadingEnabled = true;

接下来,我按以下方式更改了Traits集合:

public virtual ObservableCollection<Trait> Traits { get; set; }

将其设为虚拟允许 自动生成的代理 懒洋洋地加载特征。而已!恕我直言,我认为MSDN文档应该在POCO EF 4.2编码约定中大声说出这个负载并明确。再次感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

您的连接方法似乎没有数据的原因有几个。要加载相关数据,您需要:

  • 明确加载数据
  • 满足延迟加载要求,或
  • 使用Include()
  • 使用预先加载

我的猜测是你关闭了虚拟代理。这里有更多要求:

http://msdn.microsoft.com/en-us/library/dd456855.aspx

答案 1 :(得分:2)

如果您不使用延迟加载,则必须明确告知EF使用Include方法加载关系:

foreach (var animal in db.Animals.Include(a => a.Traits))
{
    foreach (var trait in animal.Traits)
    {
        //...
    }
}

您可以在this article中了解有关预先加载的更多信息。