C# linq to 实体包含条件和排序

C# linq to entity include with condition and ordering

我有以下(简化的)设置:

Public class parent
{
    public string name{get;set;}

    public list<child> childList {get;set;}
}


Public class child
{
    public int id {get;set;}

    public bool imported{get;set;}

    public dateTime? timeSpan {get;set;}
}

我有这个查询:

var relevant = context.parent
                .include(x => x.child.OrderByDescending(y => y.id).FirstOrDefaultAsync(z => z.imported == false && timeSpan == null)
                .Where(x => x.child != null);

这是行不通的。

基本上,我试图包括所有 parents children,但按 id 降序排列它们,然后检查第一个(例如最新的)是否有 imported == falsetimeSpan == null,并且只包括 parent 行 child 满足此条件。

我知道我可以做到:

var relevant = context.parent
                .include(x => x.child);

然后提取我需要的数据,但是可以使用 Linq 一次完成吗?

由于您正在使用标签 linq-to-entities 我假设您正在使用 entity framework.

在我看来,您在 Parent 和 Child 之间建立了一个 one-to-many 关系模型:每个 Parent 都有零个或多个 Children,每个 Child 正好属于一个 Parent.

也可能是你们有many-to-many关系。 类 略有不同(数据库将有一个你在 DbContext 中没有的额外 table),但问题仍然存在。

这可能是因为你的简化,但我在你的 类 中看到一些奇怪的东西可能会导致你的问题。

在entity framework中,正确的one-to-many关系建模如下:

public class Parent
{
    public int Id {get;set;}
    public string name{get;set;}

    // Every parent has zero or more Children
    public virtual ICollection<Child> Children {get;set;}
}

public class Child
{
    public int id {get;set;}
    public bool Imported{get;set;}
    public DateTime? TimeSpan {get;set;}

    // every Child belongs to exactly one Parent using foreign key
    public int ParentId {get; set;}
    public Parent Parent {get; set;}
}

你的Parent中Children的collection不能是List。 ChildList[3] 是什么意思?

此外,这个Collection应该是虚拟的(参见SO: Understanding code first virtual properties

您写道:

Basically, I am trying to include all the parents children, but order them by id descending and then check if the first one (eg newest one) has imported == false and timeSpan == null, and only include the parent rows that have a child that meets this condition.

有点难理解,但看起来你有一个 Parent 序列,你只想要那些 Parent 和它们的 children,其中 [=具有最高 ChildId 的 40=] 未导入且具有空 TimeSpan。

var result = dbContext.Parents
    .Select(parent => new
    {
        // Take all Parent properties you need in your end result, for example
        Id = parent.Id,
        Name = parent.Name,
        Children = parent.Children
            .OrderByDescending(child => child.Id),
    })
    .Select(parent => new
    {
        Id = parent.Id,
        Name = parent.Name,
        Children = parent.Childrent,
        NewestChild = parent.Children.FirstOrDefault(),
    })
    // keep only the parents you want to keep:
    .Where(parent => parent.NewestChild != null
       && !parent.NewestChild.Imported
       && parent.NewestChild.TimeSpan == null));