Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于导航属性的LINQ过滤器_C#_Entity Framework_Linq - Fatal编程技术网

C# 基于导航属性的LINQ过滤器

C# 基于导航属性的LINQ过滤器,c#,entity-framework,linq,C#,Entity Framework,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; } } p

我有以下两个实体:

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; }
}
但EF Core显然无法做到这一点。项目集合将非常大>20000,因此不希望为每个人加载所有项目。
我应该怎么做?

是的,很遗憾,您不能以这种方式使用Include扩展方法,但如果您愿意使用第三方库,我建议您使用该库,您可以使用该库:

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

不过,对于查询,您可以对项目使用GroupBy和子查询

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

希望您有一些相关的索引来加速数据库端的查询

应该是这样的:

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

你没有在物品类中遗漏像PersonId这样的东西吗?你是对的@PeterSchneider。我没有完全复制实体类。我现在编辑了这个。我不完全理解@Sinatr。如果我简单地说_context.Persons.Includee=>e.Items.ToList;,它将加载此列表中的所有项目,对吗?是的,很遗憾您误用了Include。对于查询,请使用Where并直接选择OrderBy。Include用于应在结果中加载的实体。您不能在include中执行一些复杂的子查询。一如既往:使用投影新{…}。谢谢!我曾考虑过查询项目列表,但有可能某人没有任何项目,在其中我仍然希望返回此人,但项目列表为空。我是否可以将此查询与_context.Persons.Includee=>e.Items.ToList组合;在某种程度上?此外,索引应该在项目上。PersonId?关于索引:是的,索引应该在PersonId上,然后按您期望的顺序在日期上。关于没有项目的人,不幸的是,这种方法只会给至少有一个项目链接的人。您还可以检索所有未链接任何项目的人员,从表项目中选择所有唯一的personId,然后选择id不在此列表中的人员,但我不确定其性能,可能还有另一种更简单的方法。啊,你可以用上面对项目的查询结果做一个人员的左连接。当然,我缺少了你需要的实际投影:我不想在单个查询中使用更多的第三方库。关于第三个选项,有没有一种简单的方法来检索p.Items=persons.Items的Person对象?嗨@laurensvm,对不起,我不太理解这个问题,但是如果你问我是否可以用查询项目的结果投影一个新的Person对象,那么没有,EF不会允许你这么做,我想我会重写我的代码来使用你的第三个选项。谢谢你的帮助!
_context.Items.GroupBy(i => i.PersonId)
    .Select(g => g.OrderByDescending(p => p.Date).FirstOrDefault())