【问题标题】:Entity framework. Need help filtering results实体框架。需要帮助过滤结果
【发布时间】:2013-01-09 14:21:31
【问题描述】:

需要在实体框架中选择数据,但需要过滤子孙

我有 4 张桌子。 Parent -> Child -> GrandChild -> GreatGrandChild我想返回所有的父母,但过滤孩子和曾孙。

换句话说(例如)

SELECT     Parent.* 
FROM       Parent 
INNER JOIN Child      
INNER JOIN Grandchild 
INNER JOIN GreatGrandChild 
WHERE      child.Column5           =  600   AND
           GreatGrandChild.Column3 = 1000 

它不能是匿名类型,因为我需要更新数据并将更改保存到数据库。

使用 vs 2010 和 EF 4.0

【问题讨论】:

  • 在您的示例 sql 中,我假设应该有连接条件?即Child.ParentID = Parent.ParentID.
  • 请注意重复发布。 stackoverflow.com/questions/14524030
  • 是的,有加入标准,我只是为了简洁而没有把它放进去。
  • @DexterMorgan 在某些情况下,简洁可能会损害问题或导致人们认为您遗漏的概念比您的问题所暗示的要多。你要么最终得到可能不正确的假设,要么像这样评论线程:)
  • 对不起,这就是我想要完成的。这些是真正的表格和真正的 SQL,它们会产生我想要的 SELECT Person.* FROM Person P INNER JOIN Plan PL ON P.PersonID = PL.PersonID INNER JOIN Coverage C on PL.PlanID = C.PlanID INNER JOIN CoveredMember CM在 C.CoverageID = CM.CoverageID WHERE CM.TermDate = NULL AND PL.PlanType = 1

标签: c# entity-framework filtering


【解决方案1】:

使用 linq 你应该需要这样的东西。

var q = from q1 in dbContext.Parent
        join q2 in dbContext.Children
        on q1.key equals q2.fkey
        join q3 in  ........
        where q4.col1 == 3000
        select q1;

【讨论】:

  • 你错过了这里的连接,并假设每个孩子只有一个。
  • 不是真的,连接是由我正在使用的导航属性完成的。如果有多个子列表,则列表将有多个记录。然后你可以使用 .Distinct()
  • 我已经尝试过了,但我似乎无法到达 GrandChild。在 o.Child 我输入点之后,孙子不是一个选项。在这些表上设置了一对多的关系。我确信是我做错了什么。有什么建议吗?
  • 也许我应该提一下,父母可以有很多孩子> 孩子可以有男孙> 孙可以有很多曾孙
  • @MiguelMatos 在您的情况下,使用导航属性,o.Children 将是一个列表,并且没有 GrandChildren 属性(列表的每个实体都将)。我不相信 EF 会支持这样的隐式连接吗?
【解决方案2】:

您的表结构 - 如果您的示例不仅仅是为了说明,我认为您可能想在这里更多地考虑您的模型(即子实体类型是独立的实体类型还是应该是定义的关系?)

您描述的是一个简单的连接和 where 子句,并且基本上以相同的方式编写:假设您从 DBContext 返回 DBSet:

_context.Parents.Join(context.Child, p=>p.Parent.ID, c=>c.ParentID)
.Join(...Grandchild...).Where(o=>o.Column5=600)
.Join(...GreatGrandChild...).Where(o=>o.Column3=1000)

EDIT 以取回您可能需要执行以下操作的强类型实体:

var greatgrandchildren = context.GreatGrandchildren.Where(o=>o.Column3=1000).ToList();
var grandchildren = context.Grandchildren.Where(o=>o.Column3=600 and greatgrandchildren.contains(o)).ToList();     
var children = context.Children.Where(o=>grandchildren.Contains(o)).ToList();
var parents = context.Parent(o=>children.Contains(o).ToList();

我的语法可能已关闭,有人可以添加,我可以避免使用 .ToList() 来防止往返直到最后一次调用吗?

【讨论】:

  • 孩子必须有父母。但是父母可以有很多孩子。和孙子们一样。必须有一个孩子,但一个孩子可以有很多孙子和曾孙。模型正确,关系设置正确
  • 此连接适用于哪个 - 您的最后一个要求有一个遗漏:尝试记住如何在此处仅返回父对象。
  • 我所说的关系表的意思是,作为一个带有定义人与人之间关系的附加表的人员表,这不是更好吗?您的模型是否需要支持人们在层次结构中改变位置? IE。添加曾曾孙需要一个额外的表,或者对于一个孩子有一个曾孙是否意味着它们将同时存在于子表和父表中?
  • 如果有意义的话,我实际上希望访问整个对象树。我的印象是在实体框架中。我可以从数据库中返回父母和所有的孩子和有孙辈的孩子等。(同时应用该过滤器)。这是一个错误的假设吗?
  • 不,永远不需要换地方。这些不是我认为是最简单的描述方式的表的真实名称。
【解决方案3】:

这个查询应该做你想做的事。是的,它有点乱,因为它嵌套得太深了。

var result = context.Parent
                    .Where(parent => parent.Child
                                           .Any(child => (child.Column5 == 600) &&
                                                          child.GrandChild
                                                               .Any(grandchild => grandchild.GreatGrandChild
                                                                                            .Any(greatgrandchild => greatgrandchild.Column3 == 1000))));

【讨论】:

  • parent.Child.GrandChild 不起作用,因为 Child 是一个列表。在我上面的 cmets 中,我解释说父母可以有很多孩子。每个孩子都可以有很多孙子 每个孙子都可以有很多曾孙
  • @DexterMorgan 他写这篇文章的方式应该也可以,只是缺少了额外的 GreatGrandChildren 表。
  • 查询不包含parent.Child.GrandChild。 ;) 并且没有必要处理GreatGrandChild,因为它们既不被检索也不用于约束结果。
  • 我的错 - 我使用 GrandChild 而不是 GreatGrandChild 因为我误读了这个问题。更新我的答案。
  • 这不起作用。 ANY 产生的外连接返回太多数据。我对 EF 有点失望,因为这太难了。这是我的真实世界示例 Person > Plan > PlanCoverage > CoveredMembers 每个人都可以有很多计划。每个计划可以有许多承保范围。每个coverage 可以有许多 CoveredMembers。我想在 Plan.PlanType = 1 和coveredMember.TermDate = null 上应用过滤器,这应该返回未终止的医疗计划中的所有人员。我想归还父母和所有孩子(一直到被保险人)
猜你喜欢
  • 2019-07-18
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多