Linq2Entities等效查询父母/子女关系,与所有父母和子女,过滤/订购儿童

时间:2014-03-13 05:03:21

标签: linq entity-framework linq-to-entities entity-framework-6

所以这个问题太长了,所以让我们去看看代码吧。给定的实体(表格)如下所示,linq2entities等效于以下Sql:

Parent
---
parent_id
parent_field1

Child
--
child_id
parent_id
child_field1
child_field2

sql:

select p.*, c.* 
from parent p 
inner join p on 
  p.parent_id = child.parent_id
where
  c.child_field1 = some_appropriate_value
order by
  p.parent_field1
  c.child_field2

L2E让你做.include(),这似乎是坚持孩子的排序和过滤的合适位置,但是include方法不接受表达式(为什么不!?)。所以,我猜这是不能立刻做的,因为这是很多文章所说的,但它们已经老了,我想知道EF6是否可行。

另外,我无法访问上下文,因此我需要lambda语法版本。

我正在寻找一个看起来像这样的结果对象层次结构:

Parent1
  |
  +-- ChildrenOfParent1
  |
Parent2
  |
  +-- ChildrenOfParent2

等等。该列表最终将成为IEnumerable。如果一个遍历该列表,则可以获得该列表中每个父项的.Children属性。

理想情况(我想在这里做梦),结果列表的整体大小可能会受到限制。例如,如果有三个父母,每个有10个孩子,总共33个(30个孩子+ 3个父母)实体,我可以将总列表限制为某个任意值,比如13,在这种情况下,这将限制结果设置为第一个父项及其所有子项,第二个父项只有一个子项(总共13个实体)。我猜这一切都必须在代码中手动完成,这是令人失望的,因为它可以在SQL中很容易地完成。

2 个答案:

答案 0 :(得分:1)

当您使用dbentityframewrok获取查询以获取父项时,将在单个查询中提取父项的字段。现在你有这样的结果集:

var parentsQuery = db.Parents.ToList();

然后,如果您在父级上有foreign key,则entityframework会在父级上创建一个navigation property来访问corresponding entity(例如{{1}表)。

在这种情况下,当您使用已经提取的Child navigation property时,parent entitieschilds创建另一个与entityframework的连接每个父母。

例如,如果sql server的计数为parentsQuery,则通过以下查询15创建entityframework另一个连接,并获取15另一个15

query

在这些情况下,当您尝试在单个查询中获取父级时,您可以使用var Childs = parentsQuery.SelectMany(u => u.NavigationProperty_Childs).ToList(); 来阻止额外连接以及include获取所有childs

parent

然后通过关注var ParentIncludeChildsQuery = db.Parents.Include("Childs").ToList(); Query没有创建任何连接,也没有再次获得任何查询:

entityframework

但是,您无法使用include创建任何条件和约束,您可以在使用var Childs = ParentIncludeChildsQuery.SelectMany(u => u.NavigationProperty_Childs).ToList(); WhereJoin之后检查任何约束或条件,等等,像这样:

Contains

但是通过此查询,所有孩子都是在var Childs = ParentIncludeChildsQuery.SelectMany(u => u.NavigationProperty_Childs .Where(t => t.child_field1 = some_appropriate_value)).ToList(); 之前提取的

获取等效sql查询的更好方法是:

database

答案 1 :(得分:0)

根据你的评论,这就是你想要的:

var query = parent.Join(child,
            p => p.ID,
            c => c.ParentID,
            (p, c) => new { Parent = p, Child = c })
        .Where(u => u.Child.child_field1 == some_appropriate_value)
        .GroupBy(u => u.Parent)
        .Select(u => new { 

            Parent = u.Key,
            Childs = u.OrderBy(t => t.Child.child_field2).AsEnumerable()
        })
        .OrderBy(u => u.Parent.parent_field1)
        .ToList();