提问者:小点点

导航属性上的LINQ筛选器


我有以下两个实体:

public class Person 
{ 
    public Person() 
    {
        Items = new HashSet<Item>();
    }

    public string Id { get; set; }
    public string Name { get; set; }
    public ICollection<Item> Items { get; private set; }
}

public class Item
{
    public string Id { get; set; }
    public DateTime Date { get; set; }
    public string Status { get; set; }
    public Person Person { get; set; }
    public string PersonId { get; set; }
}

我想选择所有的人,并且只包括他们最近的项目(按日期排序)。

我想这样的办法应该管用:

var persons = _context.Persons
    .Include(e => e.Items.OrderByDescending(i => i.Date).Take(1))
    .ToList();

但显然EF Core无法做到这一点。 items集合将变得非常大(>20000),因此不希望为每个人加载它们。 我该怎么做呢?


共2个答案

匿名用户

是的,不幸的是,您不能以这种方式使用include扩展方法,但是如果您愿意使用第三方库,那么我建议您使用Entity Framework Plus,使用该库您可以做到:

var persons = _context.Persons
                      .IncludeFilter(e => e.Items.OrderByDescending(i => i.Date).Take(1))
                      .ToList();

有第二个选项解释在链接中我张贴使用全局过滤器,但我认为这个解决方案是接近什么你正在寻找。

第三种选择是用您期望的结果投射查询:

var persons = _context.Persons
                      .Select(e=> new {Person=e,
                                       Item=e.Items.OrderByDescending(i => i.Date)
                                                   .Take(1)
                                       })
                      .ToList();

匿名用户

是的,不幸的是误用了include

但是,对于查询,可以在items上使用groupby和子查询。

查询按PersonId分组,按组内日期排序的项目,并首先获取这些项目。

希望您将有一些相关的索引来加快db端的查询速度。

应该是这样的:

_context.Items.GroupBy(i => i.PersonId)
    .Select(g => g.OrderByDescending(p => p.Date).FirstOrDefault())