Entity framework core EF核心中包含的过滤

Entity framework core EF核心中包含的过滤,entity-framework-core,Entity Framework Core,我正在尝试筛选初始查询。我已经嵌套了一个模型的包含叶。我正在尝试根据其中一个包含上的属性进行筛选。例如: 使用(var context=new BloggingContext()) { var blogs=context.blogs .Include(blog=>blog.Posts) .ThenClude(post=>post.Author) .ToList(); } 我怎么能说.Where(w=>w.post.Author==“me”)?不可行 关于这一主题正在进行讨论: 我建议您查找此

我正在尝试筛选初始查询。我已经嵌套了一个模型的包含叶。我正在尝试根据其中一个包含上的属性进行筛选。例如:

使用(var context=new BloggingContext())
{
var blogs=context.blogs
.Include(blog=>blog.Posts)
.ThenClude(post=>post.Author)
.ToList();
}
我怎么能说
.Where(w=>w.post.Author==“me”)

不可行

关于这一主题正在进行讨论:


我建议您查找此处列出的任何第三方库,例如:

您也可以反向搜索

{
    var blogs = context.Author
    .Include(author => author.posts)
        .ThenInclude(posts => posts.blogs)
    .Where(author => author == "me")
    .Select(author => author.posts.blogs)
    .ToList();
}

我使用过的最简单的内联解决方案如下:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .FromSql("Select b.* from Blogs b inner join Posts p on b.BlogId = p.BlogId where p.Author = 'me'")
        .ToList();
}
不确定Include()和Include(),但只需一个Include即可:

var filteredArticles = 
    context.NewsArticles.Include(x => x.NewsArticleRevisions)
    .Where(article => article.NewsArticleRevisions
        .Any(revision => revision.Title.Contains(filter)));
希望这有帮助

尽管使用EF Core不可行(仍在讨论中),但我已经设法通过EF Core数据库集使用Linq to Entities实现了这一点。在您的情况下,而不是:

var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList()
。。您将有:

await (from blog in this.DbContext.Blogs
           from bPost in blog.Posts
           from bpAuthor in bPost.Author
           where bpAuthor = "me"
           select blog)
.ToListAsync();

EntityFrameworkCore5是第一个使用的EF版本

工作原理 支持的操作:

  • 其中
  • OrderBy(降序)/然后by(降序)
  • 跳过
  • Take
一些用法示例(来自和) :

每个导航只允许一个筛选器,因此对于需要多次包含同一导航的情况(例如,在同一导航上包含多个筛选器),请仅应用筛选器一次,或者对该导航应用完全相同的筛选器

context.Customers
.Include(c=>c.Orders.Where(o=>o.Name!=“Foo”))。然后Include(o=>o.OrderDetails)
.Include(c=>c.Orders)。然后Include(o=>o.Customer)

context.Customers
.Include(c=>c.Orders.Where(o=>o.Name!=“Foo”))。然后Include(o=>o.OrderDetails)
.Include(c=>c.Orders.Where(o=>o.Name!=“Foo”))。然后Include(o=>o.Customer)
另一个重要注意事项:

使用新筛选操作包含的集合将被视为已加载

这意味着,如果启用了延迟加载,解决上一个示例中一个客户的
订单
集合将不会触发整个
订单
集合的重新加载

此外,同一上下文中的两个后续过滤的
Include
s将累加结果。例如

context.Customers.Include(c=>c.Orders.Where(o=>!o.IsDeleted))
…然后是

context.Customers.Include(c=>c.Orders.Where(o=>o.IsDeleted))
…将导致
客户
拥有包含所有订单的
订单
集合

过滤包含和关系修复 如果将其他
订单
加载到同一上下文中,由于关系修复,可能会将更多订单添加到
customers.Orders
集合中。这是不可避免的,因为EF的变化跟踪系统是如何工作的

context.Customers.Include(c=>c.Orders.Where(o=>!o.IsDeleted))
…然后是

context.Orders.Where(o=>o.IsDeleted.Load();
…将再次导致
客户
拥有包含所有订单的
订单
集合

筛选包含vs筛选查询 过滤的
Include
在如何影响整个查询的过滤方面引起了一些混乱。经验法则是:它不会

声明

context.Customers.Include(c=>c.Orders.Where(o=>!o.IsDeleted))
…返回上下文中的所有客户,而不仅仅是具有未删除订单的客户。
Include
中的过滤器不影响主查询返回的项目数

另一方面,声明

context.Customers
.Where(c=>c.Orders.Any(o=>!o.IsDeleted))
.包括(c=>c.订单)
…仅返回至少有一个未删除订单,但其所有订单都在
订单
集合中的客户。主查询上的筛选器不影响由
Include
返回的每个客户的订单

要获取具有未删除订单且仅加载其未删除订单的客户,需要两个筛选器:

context.Customers
.Where(c=>c.Orders.Any(o=>!o.IsDeleted))
.包括(c=>c.Orders.Where(o=>!o.IsDeleted))
过滤包括和预测 另一个混乱的领域是过滤的
包括
和投影(
选择新的{…}
)是如何关联的。简单的规则是:投影忽略
包含
s,过滤或不过滤。像这样的疑问

context.Customers
.包括(c=>c.订单)
.Select(c=>new{c.Name,c.RegistrationDate})
…将生成SQL而不加入到
订单
。至于EF,它与

context.Customers
.Select(c=>new{c.Name,c.RegistrationDate})
当过滤
包含
时,它会变得混乱,但在投影中也会使用
顺序

context.Customers
.包括(c=>c.Orders.Where(o=>!o.IsDeleted))
.选择(c=>new
{ 
c、 名字,
c、 注册日期,
OrderDates=c.Orders.Select(o=>o.DateSent)
})
人们可能认为,
OrderDates
只包含未删除订单的日期,但它们包含所有
订单的日期。同样,投影完全忽略了
Include
。投影和包含是两个独立的世界

这个问题有趣地证明了他们对自己生活的严格程度:

context.Customers
.包括(c=>c.Orders.Where(o=>!o.IsDeleted))
.选择(c=>new
{ 
客户=c,
OrderDates=c.Orders.Select(o=>o.DateSent)
})
现在暂停片刻,预测结果

不那么简单的规则是:投影可以
var query = _context.Employees
            .Where(x =>
                x.Schedules.All(s =>
                    s.ScheduleDate.Month != DateTime.UtcNow.AddMonths(1).Month &&
                    s.ScheduleDate.Year != DateTime.UtcNow.AddMonths(1).Year) ||
                (x.Schedules.Any(s =>
                     s.ScheduleDate.Month == DateTime.UtcNow.AddMonths(1).Month &&
                     s.ScheduleDate.Year == DateTime.UtcNow.AddMonths(1).Year) &&
                 x.Schedules.Any(i => !i.ScheduleDates.Any())));

        var employees = await query.ToListAsync();

        await query.Include(x => x.Schedules)
            .ThenInclude(x => x.ScheduleDates)
            .SelectMany(x => x.Schedules)
            .Where(s => s.ScheduleDate.Month == DateTime.UtcNow.AddMonths(1).Month &&
                        s.ScheduleDate.Year == DateTime.UtcNow.AddMonths(1).Year).LoadAsync();
var list = context.Blogs.IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted))
                .IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted)
                    .SelectMany(y => y.Comments.Where(z => !z.IsSoftDeleted)))
                .ToList();
GetContext(session).entity
                .Include(c => c.innerEntity)
                .Select(c => new Entity()
                {
                    Name = c.Name,
                    Logo = c.Logo,
                    InnerEntity= c.InnerEntity.Where(s => condition).ToList()
                })