簡體   English   中英

EF 5中的急切加載因深度圖失敗(使用.include())

[英]Eager Loading in EF 5 fails with deep graph (using .include())

我首先在EF 5中使用代碼。這是我的測試域

    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; }
}

這是我的上下文:

    public class TestContext : DbContext
{
    public TestContext()
        :base()
    {
    }
    public TestContext(string connectionString)
        : base(connectionString)
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Master>()
            .Property(m => m.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Master>()
            .HasKey(m => m.Id);

        modelBuilder.Entity<Query>()
            .Property(q => q.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Query>()
            .HasKey(q => q.Id);
        modelBuilder.Entity<Query>()
            .HasOptional(q => q.Master)
            .WithOptionalPrincipal(m => m.Query);
        modelBuilder.Entity<Query>()
            .HasOptional(q => q.SpecialChild)
            .WithOptionalPrincipal(c => c.SpecialQuery);

        modelBuilder.Entity<ChildA>()
            .Property(c => c.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<ChildA>()
            .HasKey(c => new { c.Query_Id, c.Id });
        modelBuilder.Entity<ChildA>()
            .HasRequired(c => c.Query)
            .WithMany(q => q.ChildrenA)
            .HasForeignKey(c => c.Query_Id);

        modelBuilder.Entity<ChildB>()
            .Property(c => c.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<ChildB>()
            .HasKey(c => new { c.Query_Id, c.Id});
        modelBuilder.Entity<ChildB>()
            .HasRequired(c => c.Query)
            .WithMany(m => m.ChildrenB)
            .HasForeignKey(c => c.Query_Id);
    }

    public DbSet<Master> Masters { get; set; }
    public DbSet<ChildA> ChildrenA { get; set; }
    public DbSet<ChildB> ChildrenB { get; set; }
}

注意:當從POCO類的集合中刪除對象時,復合PK允許EF強制實體刪除。

這是一些加載測試數據的代碼:

            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();
        }

現在,您將看到從ChildB到Query的可選關系。 因此,ChildB可以有一個查詢,然后可以擁有自己的ChildA和ChildB列表。 在實踐中,它是如此深入。

當我查詢Master並通過在查詢的最低級別(Master.Query.ChildrenB.SpecialQuery.Children [A或B])上使用include()來強制進行快速加載時,則僅加載一個集合(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中的集合加載得很好。

我在這里想念什么嗎?

非常感謝所有助手。

我沒有任何解釋,只是使用SQL Server 2008 R2 Express在VS 2010中的.NET 4.0上對EF 5.0進行了測試。 我已經復制並粘貼了您的代碼,但是刪除了顯式連接字符串,因為顯然您正在使用SQL Server CE 4.0。

對我來說,它按預期工作,這就提出了一個問題,即SQL Server CE提供程序是否在此處存在錯誤。

我唯一的區別是,有問題的ChildB(我認為是"ChildB3" )在我的集合中具有索引3,而不像在測試中那樣具有索引2。 在刪除所有virtual關鍵字以禁用延遲加載后,我也進行了測試,但結果相同(成功)。

我的測試截圖:

很多包括

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM