【问题标题】:EntityFramework 5 filter an included navigation propertyEntity Framework 5 过滤器并包含导航属性
【发布时间】:2013-02-06 22:30:08
【问题描述】:

我想找到一种使用 Linq 将导航属性过滤到相关实体子集的方法。我知道围绕这个主题的所有答案都建议使用匿名选择器,例如:

query.Where(x => x.Users.Any(y => y.ID == actingUser.ID))
    .Select(x => new
    {
        Event = x,
        Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())
    })
    .OrderBy(x => x.Discussions.Count())
    .ThenBy(x => x.Event.Name);

但是,由于我们的查询生成的一般性质,这远不理想,并且如果您抛出分析器,也会产生非常可怕的 sql 查询。

我希望能够完成类似的事情:

query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()))
        .OrderBy(x => x.Discussions.Count())
        .ThenBy(x => x.Name);

我意识到这在 EF5(或任何版本)中不受支持,但必须有一种方法可以通过 Linq 完成对结果集的约束,而无需深入研究匿名类型选择语句。

我已经尝试过做一些事情:

query.GroupJoin(discquqery, 
    x => x.ID,
    x => x.Event.ID, 
    (evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList();

但是,您不能在 lambda 表达式中进行赋值,并且在此处选择匿名类型会导致与使用 select 时相同的困境。

我想我无法理解为什么 EF 不提供(我能找到的)生成方式:

SELECT
    --Properties
FROM Event e
LEFT OUTER JOIN Discussions d
    ON e.ID = d.EventID AND --Additional constraints
WHERE
    --Where conditions
ORDER BY
    --Order Conditions

在 SQL 中约束连接非常简单,必须有一种方法通过 Linq 来完成。

PS:我已经搜索过 stack、MSDN、experts-exchange 等。请注意这不是重复的。任何甚至涉及到这个主题的东西要么有一个“无法完成”的答案,要么根本没有答案。没有什么是不可能的……包括这个。

【问题讨论】:

  • 嗯,这是一个“可以做到”的答案:stackoverflow.com/a/13904825/861716
  • 有一些方法可以扩展 EF 中的查询生成引擎。所以这不是不可能的,如果这是唯一的途径,那么答案是对 EF 查询引擎的扩展,以允许 INNER / OUTER JOIN 包含额外的过滤器。没有什么是不可能的......如果我必须重新编译 EF,那么我会......它没有现有的答案意味着答案是自己构建的(我目前甚至当我问这个问题时,计划这样做)

标签: c# linq entity-framework-5


【解决方案1】:

任何涉及到这个主题的东西要么有一个逃避“它不能 完成”回答或根本没有回答。没有什么是不可能的...... 包括这个。

当然。有可能的。您可以下载 EF 源代码并自行添加此功能。这将对开源项目和社区做出巨大贡献。我相信 EF 团队会很乐意为您提供帮助。

使用当前版本“无法完成”is the answer。您可以使用投影到匿名或特殊未映射类型,如您在问题开头所述。其他选项是单独的显式查询以加载单个父项的相关实体或单独的查询以加载所有父项的相关实体。

为单亲加载关系:

context.Entry(event)
       .Collection(e => e.Discussions)
       .Query()
       .Where(d => ...)
       .Load();

为所有父母加载关系(需要关闭延迟加载):

// load all parents
var events = query.Where(e => ...).ToList();

// load child filtered by same condition for parents and new condition for children
childQuery.Where(d => e.Event ... && d.Something ...).Load();

第二种解决方案要求子级将导航属性返回给父级(用于构造最初用于加载父级的相同查询条件)。如果您正确配置了所有内容并且附加了实体,EF 应该自动修复您在父实体中的关系(集合)(但它不会将动态代理中的集合标记为已加载,这就是您不能将其与延迟加载一起使用的原因)。

【讨论】:

  • 那么显然我正在扩展 EF5 核心。你知道有没有办法扩展而不是修改和重新编译整个DLL?
  • 您必须重新编译 DLL。您可以访问 EF codeplex site 并直接与 EF 团队讨论此贡献 - 他们可能已经对此功能进行了一些高级设计并与您分享。
  • 投票支持过滤的 Include here!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-14
  • 2014-12-21
相关资源
最近更新 更多