过滤包含在EF Core中

时间:2017-04-25 18:12:25

标签: entity-framework-core

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

'include_dirs': [
    ...
],
'conditions': [
  ['OS=="win"', {
    'include_dirs': [
        '<!(echo %OPENSSL_DIR%)/include',
        '<!(echo %BOOST_DIR%)',
        '<!(echo %SQLITE_DIR%)'
    ]
  }],
  ['OS!="win"', {
    'include_dirs': [
        '<!(echo $OPENSSL_DIR)/include',
        '<!(echo $BOOST_DIR)',
        '<!(echo $SQLITE_DIR)'
    ]
  }]
]

我怎么能说line-height: 0;

8 个答案:

答案 0 :(得分:43)

最后,此功能has been implemented在EF Core版本5.0.0中。请参阅EF核心的documentation

支持的操作

  • Where
  • OrderBy(Descending)/ThenBy(Descending)
  • Skip
  • Take

一些用法示例(来自original feature request):

每个导航仅允许使用一个过滤器,因此对于需要多次包含同一导航的情况(例如,同一导航上包含多个ThenInclude),请仅对该过滤器应用一次,或对该导航应用完全相同的过滤器。

customers
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
    .Include(c => c.Orders).ThenInclude(o => o.Customer)

customers
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
    .Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.Customer)

另一个重要说明:

使用新的过滤器操作包含的集合被视为已加载。

这意味着如果启用了延迟加载,则从上一个示例访问customers.Orders不会触发整个Orders集合的重新加载。

另一方面,如果将其他Order加载到同一上下文中,则由于关系修正,它们中的更多可能会添加到customers.Orders集合中。由于EF的变更跟踪器的工作原理,这是不可避免的。

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

customers.Include(c => c.Orders.Where(o => !o.IsDeleted))

...之后是...

customers.Include(c => c.Orders.Where(o => o.IsDeleted))

...将导致customers的{​​{1}}集合包含所有订单。

答案 1 :(得分:15)

不可行。

有关此主题的持续讨论: https://github.com/aspnet/EntityFramework/issues/1833

我建议四处寻找那里列出的任何第三方图书馆,例如:https://github.com/jbogard/EntityFramework.Filters

答案 2 :(得分:7)

您也可以撤消搜索。

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

答案 3 :(得分:1)

不确定Include()和ThenInclude(),但是使用单个include即可轻松做到这一点:

var filteredArticles = 
    context.NewsArticles.Include(x => x.NewsArticleRevisions)
    .Where(article => article.NewsArticleRevisions
        .Any(revision => revision.Title.Contains(filter)));

希望这会有所帮助!

答案 4 :(得分:1)

尽管它(仍在讨论中)不适用于EF Core,但我已经设法通过Linq to Entities over EF Core DbSet来做到这一点。在您的情况下,而不是:

include OtherAPI

..您将拥有:

var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList()

答案 5 :(得分:1)

我使用了下面的包 使用 Z.EntityFramework.Plus

IncludeFilter 和 IncludeFilterByPath 两种方法是你可以使用的。

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

这是示例https://dotnetfiddle.net/SK934m

或者你可以这样做

GetContext(session).entity
                .Include(c => c.innerEntity)
                .Select(c => new Entity()
                {
                    Name = c.Name,
                    Logo = c.Logo,
                    InnerEntity= c.InnerEntity.Where(s => condition).ToList()
                })

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

可以通过两个查询来完成此任务。例如:

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