簡體   English   中英

實體框架 - 急切加載過濾器?

[英]Entity Framework - Eager loading with filter?

我正在使用數據庫架構,在更新時不會覆蓋記錄。 而是添加記錄的新副本並標記為“當前”。

例如:

Id | Current | Name | Owner
1  | false   | Foo  | Bar
1  | false   | Foo  | Bazz
1  | true    | Foo  | Buzz

在我的模型中,我有一個Blog實體,其中包含許多與之相關的Post 每個Post都有很多與之相關的Comment

public class Blog
{
    public int Id {get; set};
    public bool Current {get; set};
    public ICollection<Post> Posts {get; set;}
}

public class Post
{
    public int Id {get; set};
    public bool Current {get; set};
    public ICollection<Comment> Comments {get; set;}
}

public class Comment
{
    public int Id {get; set};
    public bool Current {get; set};
}

我想熱切地加載一個Blog及其所有Post和所有Comment ,就像在MSDN的這個例子中一樣:

using (var context = new BloggingContext()) { // Load all blogs, all related posts, and all related comments var blogs1 = context.Blogs .Include(b => b.Posts.Select(p => p.Comments)) .ToList(); }

但是,我想只包含其中Current == true DB記錄。 如何使用LINQ-to-EF執行此操作? 理想情況下,條件會進入JOINON子句 - 這可能嗎?

免責聲明 :我是項目Entity Framework Plus的所有者

EF + Query IncludeFilter允許輕松過濾包含的實體。

using (var context = new BloggingContext()) 
{ 
  // Load all blogs, all related posts, and all related comments 
  var blogs1 = context.Blogs 
                     .IncludeFilter(b => b.Posts.Where(x => x.Current))
                     .IncludeFilter(b => b.Posts.Where(x => x.Current).Select(p => p.Comments.Where(x => x.Current)) 
                     .ToList(); 
}

注意:由於具有導航屬性的庫的某些限制,必須包含每個路徑。

Wiki: EF + Query包含過濾器


回答子問題

一個問題:發出的SQL非常大。

SQL由Entity Framework生成。 由於它們如何處理投影和包含方法中的關系,SQL非常大。 我們的庫不生成這個SQL。

您可以使用EF + Query IncludeOptimized來更改生成的大SQL以執行多個語句。 使用多個語句通常可以提高性能。

例:

using (var context = new BloggingContext()) 
{ 
  // Load all blogs, all related posts, and all related comments 
  var blogs1 = context.Blogs 
                     .IncludeOptimized(b => b.Posts.Where(x => x.Current))
                     .IncludeOptimized(b => b.Posts.Where(x => x.Current).Select(p => p.Comments.Where(x => x.Current)) 
                     .ToList(); 
}

注意:由於具有導航屬性的庫的某些限制,必須包含每個路徑。

Wiki: EF + Query IncludeOptimized

使用基於此StackOverflow答案的 “開箱即用”實體框架找到了解決方案。

關鍵概念是向每個實體添加父屬性,然后從層次結構的最低級別“向后”向上移動到頂部:

var query = context.Comments
    .Include("Post.Blog")
    .Where(comment =>
        comment.Current &&
        comment.Post.Current &&
        comment.Post.Blog.Current )
    .Select(comment => comment.Post.Blog)
    .ToList();

在對SO答案的評論中提到的一個重要警告

...如果父母存在沒有任何與過濾器匹配的子項,那么這些父母將不在結果集中。

當使用實體框架“開箱即用”時,目前不支持使用.Include()進行預先加載時進行過濾。 你可以在這里投票贊成這個功能 ,希望它可以切入EF7。

我在一個名為EntityFramework.Include的開源庫中找到了我的問題的部分答案,它在急切加載時提供了一些過濾功能。

不幸的是,我只能將它用於我的層次結構中的兩個(三個)級別,如下所示:

using (var context = new BloggingContext()) 
{ 
    // Load all blogs and all related posts that are "Current"
    var query = context.Blogs
        .Where(b => b.Current)
        .Include(b => b.Posts, b => b.Posts.Where(p => p.Current).ToList());
    var list = query.ToListWithInclude();
}

仍然試圖弄清楚如何更深入到Comment s。

暫無
暫無

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

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