根据子标准的子项获取父对象并包含

时间:2016-07-22 09:43:04

标签: c# entity-framework linq

好的,这是我的表格的快速版本。

public class Line
{
  // Bunch Of properties
  // ...
  public List<Tool> Tools {get;set;}
}

public class Tool
{
  // Bunch Of properties
  // ...
  public List<Task> Tasks {get;set;}
}

public class Task
{
  // Bunch Of properties
  // ...
  public List<SchedItem> SchedItems {get;set;}
}

public class SchedItem
{
  public DateTime SchedDate {get;set;}
}

我想要的是一个查询,它将返回所有Lines,包括子集合及其子集合等,具体取决于SchedItem.SchedDate是否属于日期范围。

我在LinqPad中尝试了以下内容。

var line = (from p in Lines.Include(x => x.Tools.Select(m => m.Tasks.Select(s => s.SchedItems)))
                        from t in p.Tools
                        from m in t.Tasks
                        from s in m.SchedItems
                        where s.SchedDate >= StartDateQuery &&
                              s.SchedDate <= EndDateQuery 
                        select p);

这对我来说似乎不对,因为返回的数据包括所有SchedItems而不仅仅是基于查询的数据。

更新1: 是的,我认为我的理解是错误的。我在上下文配置中设置了以下内容

db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;

当我再次运行代码时,我得到了一个没有子项的33个Line项的列表。应该只有1&#39; Line&#39;带有许多儿童用品的物品。

我将查询更改为此,我现在获取子项,但Line计数仍为33,这是错误的。

var line = (from p in Lines
                        from t in p.Tools
                        from m in t.Tasks
                        from s in m.SchedItems
                        where s.SchedDate >= StartDateQuery &&
                              s.SchedDate <= EndDateQuery 
                        select p).Include(x => x.Tools.Select(m => m.Tasks.Select(s => s.SchedItems)));

2 个答案:

答案 0 :(得分:1)

试试这个

var lines = Lines.Where(i => 
    i.Tools.Any(t => 
        t.Tasks.Any(y => 
            y.SchedItems.Any(u => 
                u.SchedDate >= StartDateQuery  && 
                s.SchedDate <= EndDateQuery 
            ) 
        )
    )
);

lines.ForEach(i => new 
{
    i.Tools = i.Tools.Where(t => 
                t.Tasks.Any(y => 
                    y.SchedItems.Any(u => 
                        u.SchedDate >= StartDateQuery  && 
                        s.SchedDate <= EndDateQuery 
                    ) 
                )
            );
    i.Tools.ForEach(t => new
    {
        t.Tasks = t.Tasks.Where(y => 
                        y.SchedItems.Any(u => 
                            u.SchedDate >= StartDateQuery  && 
                            s.SchedDate <= EndDateQuery 
                        ) 
                    );
    });
});

答案 1 :(得分:1)

您的代码因成对from语句而生成笛卡尔积。 我将跳过DbContext的配置并假设您已启用延迟加载。试试这个:

var line = from p in ls
           where p.Tools
                .Any(to=> to.Tasks
                    .Any(ta=> ta.SchedItems
                       .Any(s=> s.SchedDate >= StartDateQuery && s.SchedDate <= EndDateQuery)));
           select p;

实现目标的另一种方法是将parrent添加到:SchedItem,Task,Tool,找到符合您要求的SchedItems,并通过父级导航到Line。有关更多信息,请转到here