首页 > 解决方案 > Ef core : 从列表的列表中过滤掉一个项目

问题描述

我有这种模型

public class Blog
{
   public IList<Post> Posts { get; set; }
}

public class Post
{
   public PostType PostType { get; set; }
}

public class PostType
{
   public string Code { get; set; } // "Code1" and "Code2"
}

我想要的是,返回所有带有 PostType Code1帖子的博客或没有帖子的博客(假设博客可能没有帖子)

为此,我编写了这个 Ef linq 查询:

_dbContext.Blogs.Include(b => b.Posts).ThenInclude(b => b.PostType)
    .Where(b => b.Posts.Count == 0 || b.Posts.Any(p => p.PostType.Code == "Code1").ToList();

这个查询的问题是;如果博客有Code1Code2类型的帖子,则上述查询包括代码 Code2 和 Code1 的帖子,因为使用的是Any

所以我尝试了这个:而不是Any,我使用了All

_dbContext.Blogs.Include(b => b.Posts).ThenInclude(b => b.PostType)
    .Where(b => b.Posts.Count == 0 || b.Posts.All(p => p.PostType.Code == "Code1").ToList();

但在上述情况下,此查询不返回任何内容。

在给定的情况下,有没有办法使用单个Ef LINQ 查询返回所有帖子类型为 Code1 的博客而不包括帖子类型Code2 ?

已编辑: 找到此博客... https://entityframework.net/include-with-where-clause

更新

此功能现在可在 .net EF core 5 Filtered Includes上使用

标签: c#linqef-core-2.1

解决方案


该解决方案类似于 Thierry V 的解决方案,只是将过滤后的帖子存储在单独的字典中以避免 EF 跟踪副作用:https ://docs.microsoft.com/en-us/ef/core/querying/tracking 。

但是,我无法真正看到此类代码背后的原因。通常,您会抓取所有满足您条件的博客(包含 Code1 的任何帖子),然后根据需要对其进行过滤。

var blogs = _dbContext.Blogs.Include(b => b.Posts).ThenInclude(b => b.PostType)
    .Where(b => b.Posts.Count == 0 || b.Posts.Any(p => p.PostType.Code == "Code1")
    .ToList(); 

// Storing the filterd posts in a dictionary to avoid side-effects of EF tracking.
var dictionary = new Dictionary<int, List<Post>>();
foreach (var blog in blogs) {
    dictionary[blog.BlogId] = blog.Posts.Where(p => p.PostType.Code == "Code1").ToList();
}

推荐阅读