C# EF 5中的即时加载因深度图而失败(使用.include())

C# EF 5中的即时加载因深度图而失败(使用.include()),c#,.net,ef-code-first,entity-framework-5,eager-loading,C#,.net,Ef Code First,Entity Framework 5,Eager Loading,我首先使用EF5的代码。这是我的测试域 public class Master { public int Id { get; set; } public string Name { get; set; } public virtual Query Query { get; set; } } public class Query { public Query() { ChildrenA = new HashSet<ChildA

我首先使用EF5的代码。这是我的测试域

    public class Master
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Query Query { get; set; }
}

public class Query
{
    public Query()
    {
        ChildrenA = new HashSet<ChildA>();
        ChildrenB = new HashSet<ChildB>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public Master Master { get; set; }
    public ChildB SpecialChild { get; set; }
    public virtual ICollection<ChildA> ChildrenA { get; private set; }
    public virtual ICollection<ChildB> ChildrenB { get; private set; }

    public ChildB GetChildByName(string name)
    {
        return ChildrenB.Where(c => c.Name == name).FirstOrDefault();
    }
}

public class ChildA
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Query_Id { get; set; }
    public virtual Query Query { get; set; }
}

public class ChildB
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Query SpecialQuery { get; set; }
    public int Query_Id { get; set; }
    public Query Query { get; set; }
}
现在,正如您将看到的,有一个从ChildB返回到Query的可选关系。所以一个ChildB可以有一个查询,然后可以有它自己的ChildA和ChildB列表。在实践中,这是非常深刻的

当我在查询的最低级别(Master.query.ChildrenB.SpecialQuery.ChildrenB[a或B])上使用include()查询Master并强制加载时,只加载一个集合(ChildrenA或ChildrenB)

下面是一个示例查询,它将强制加载整个图形:

            using (TestContext context = new TestContext(connectionString))
        {
            Master master = context.Masters
                        .Where(m => m.Name == "Master1")
                        .Include("Query.ChildrenA")
                        .Include("Query.ChildrenB.SpecialQuery.ChildrenA")
                        .Include("Query.ChildrenB.SpecialQuery.ChildrenB")
                        .FirstOrDefault();
            ChildB c = master.Query.GetChildByName("Child3");
        }
注意:我知道下面集合中引用实体的语法是错误的,我只是用它来说明问题

此时master.Query.ChildrenB[2]。SpecialQuery.ChildrenA.Count为1(正确) master.Query.ChildrenB[2]。SpecialQuery.ChildrenB.Count为0(应为4)

如果修改查询并删除.Include(“query.ChildrenB.SpecialQuery.ChildrenA”),则master.query.ChildrenB[2]。SpecialQuery.ChildrenB.Count按预期为4

这真的很奇怪,因为master.Query.ChildrenA和master.Query.ChildrenB中的集合加载得很好

我是不是遗漏了什么


非常感谢所有的助手。

我没有任何解释,只是在VS 2010中使用.NET 4.0上的EF 5.0,使用SQL Server 2008 R2 Express进行了测试。我复制并粘贴了您的代码,只是删除了显式连接字符串,因为您显然使用的是SQL Server CE 4.0

对我来说,它的工作原理与您预期的一样,这就提出了一个问题,即SQLServerCE提供程序是否存在缺陷

我唯一的不同之处是,所讨论的ChildB(
“ChildB3”
,我想)在我的集合中有索引3,而不是像您的测试中那样的索引2。在删除所有
virtual
关键字后,我也进行了测试,以禁用延迟加载,但结果相同(成功)

我的测试截图:


我没有任何解释,只是在VS 2010中使用.NET 4.0上的EF 5.0,使用SQL Server 2008 R2 Express进行了测试。我复制并粘贴了您的代码,只是删除了显式连接字符串,因为您显然使用的是SQL Server CE 4.0

对我来说,它的工作原理与您预期的一样,这就提出了一个问题,即SQLServerCE提供程序是否存在缺陷

我唯一的不同之处是,所讨论的ChildB(
“ChildB3”
,我想)在我的集合中有索引3,而不是像您的测试中那样的索引2。在删除所有
virtual
关键字后,我也进行了测试,以禁用延迟加载,但结果相同(成功)

我的测试截图:


您好,谢谢您的回复。我正在使用VS2012、.NET4.5和EF5。我刚刚将其切换为使用SQL Express 2012,得到了相同的结果。我将发布一个“答案”无法发布截图,不幸的是由于一些奇怪的分数没有达到,但结果仍然是一样的,一个空的ChildrenB集合。还有其他想法吗?嗯,情节越来越复杂了。我们刚刚在Win7 x64、VS2010、SQL Express 2008 R2、.Net4上安装了一个VM,所有这些都可以按照Slauma的响应正常工作。现在将工作项目移到其他环境以查看发生的情况。将工作项目移回开发环境(Windows8 x64、VS2010、SQL Server 2008 R2或SQL Server 2012 Express)并返回问题。将发布到Microsoft进行调查。您好,谢谢您的回复。我正在使用VS2012、.NET4.5和EF5。我刚刚将其切换为使用SQL Express 2012,得到了相同的结果。我将发布一个“答案”无法发布截图,不幸的是由于一些奇怪的分数没有达到,但结果仍然是一样的,一个空的ChildrenB集合。还有其他想法吗?嗯,情节越来越复杂了。我们刚刚在Win7 x64、VS2010、SQL Express 2008 R2、.Net4上安装了一个VM,所有这些都可以按照Slauma的响应正常工作。现在将工作项目移到其他环境以查看发生的情况。将工作项目移回开发环境(Windows8 x64、VS2010、SQL Server 2008 R2或SQL Server 2012 Express)并返回问题。将发布到Microsoft进行调查。
            System.Data.Entity.Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
        string connectionString = string.Format("Data Source={0};", SQLCEFileName());
        using (TestContext context = new TestContext(connectionString))
        {
            Master master = new Master() { Name = "Master1", Query = new Query() { Name = "Query1" } };
            master.Query.ChildrenA.Add(new ChildA() { Name = "ChildA1" });
            master.Query.ChildrenB.Add(new ChildB() { Name = "ChildB1" });
            master.Query.ChildrenB.Add(new ChildB() { Name = "ChildB2" });
            master.Query.ChildrenB.Add(new ChildB() { Name = "ChildB3" });
            master.Query.ChildrenB.Add(new ChildB() { Name = "ChildB4" });
            context.Masters.Add(master);
            Query special = new Query() { Name = "Special" };
            ChildB c3 = master.Query.GetChildByName("ChildB3");
            c3.SpecialQuery = special;
            special.ChildrenA.Add(new ChildA() { Name = "SpecialChildA1" });
            special.ChildrenB.Add(new ChildB() { Name = "SpecialChildB1" });
            special.ChildrenB.Add(new ChildB() { Name = "SpecialChildB2" });
            special.ChildrenB.Add(new ChildB() { Name = "SpecialChildB3" });
            special.ChildrenB.Add(new ChildB() { Name = "SpecialChildB4" });
            context.SaveChanges();
        }
            using (TestContext context = new TestContext(connectionString))
        {
            Master master = context.Masters
                        .Where(m => m.Name == "Master1")
                        .Include("Query.ChildrenA")
                        .Include("Query.ChildrenB.SpecialQuery.ChildrenA")
                        .Include("Query.ChildrenB.SpecialQuery.ChildrenB")
                        .FirstOrDefault();
            ChildB c = master.Query.GetChildByName("Child3");
        }