EntityFramework 5筛选包含的导航属性
本文关键字:导航 属性 包含 筛选 EntityFramework | 更新日期: 2023-09-27 17:58:09
我想找到一种使用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、专家交流等。请注意这不是重复的。任何涉及这个主题的东西要么有一个回避的"不可能完成"答案,要么根本没有答案。没有什么是不可能的。。。包括这个。
任何涉及这个主题的东西都会有一句"不可能"要么回答,要么根本不回答。没有什么是不可能的。。。包括这个。
当然。这是可能的。您可以下载EF源代码并自己添加此功能。这将是对开源项目和社区的巨大贡献。我相信英孚团队会很乐意帮助您的努力。
在目前的版本中,"这是不可能的"是答案。您可以使用投影到匿名或特殊的未映射类型,正如您在问题开头所描述的那样。其他选项是单独的显式查询以加载单亲的相关实体,或者单独的查询以加载所有父级的相关实体。
单亲的负载关系:
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应该自动修复父实体中的关系(集合)(但它不会将动态代理中的集合标记为已加载,因此这就是您不能将其与延迟加载一起使用的原因)。