Ef core:从列表的列表中过滤出一个项目

时间:2018-08-30 09:12:14

标签: c# linq ef-core-2.1

我有这种模型

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 的博客或无帖子的Blog(假设博客可能没有帖子)

为此,我编写了这个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();

此查询的问题是;如果博客中包含类型为 Code1 Code2 的帖子,则上面的查询将同时包含代码 Code2 Code1 的帖子因为我正在使用 Any

所以我尝试了这个:我使用的是 All

,而不是 Any
_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();

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

在给定的情况下,有一种方法可以使用单个返回所有帖子类型为代码1 的博客,而无需包括帖子类型为 Code2 的博客是linq查询吗?

2 个答案:

答案 0 :(得分:2)

该解决方案类似于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();
}

答案 1 :(得分:1)

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(); 
// blogs contains posts which have Code1, and maybe Code2

//filter the posts by assigning only the posts with Code1
blogs.ForEach(b=> b.Posts = b.Posts.Where( p => p.PostType.Code == "Code1"))