2013-02-06 49 views
15

我想找到一种使用Linq过滤导航属性到相关实体子集的方法。我知道解决这个问题的所有答案,建议做一个匿名的选择,例如:EntityFramework 5过滤一个包含的导航属性

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表达式内部分配和这里选择一个匿名类型会导致同样的困境,它并使用选择。

我想我无法理解为什么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:我已经搜索过堆栈,MSDN,专家交换等请认识到这不是重复的。甚至任何涉及这个问题的东西都有一个“不能做”答案或根本没有答案。没有什么是不可能的......包括这个

+1

那么,这里是一个“它可以做到”的答案:http://stackoverflow.com/a/13904825/861716 –

+5

有很多方法可以在EF中扩展查询生成引擎。所以这不是不可能的,如果这是唯一的路线,那么答案就是EF查询引擎的扩展,以允许INNER/OUTER JOIN包含额外的过滤器。没有什么是不可能的......如果我必须重新编译EF,那么我会......它没有现有的答案意味着答案是自己构建它(我现在甚至当我问这个问题,计划在做什么) – VulgarBinary

+4

这就是精神!! –

回答

8

任何事情甚至触及这个问题或有一个警察“它不能 被做”答案或根本没有答案。没有什么是不可能的...... 包括这一点。

肯定。有可能的。您可以下载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应该会自动修正父实体中的关系(集合)(但它不会将动态代理中的集合标记为已加载,这就是为什么你不能在延迟加载时使用它的原因)。

+0

然后显然我扩展了EF5内核。你知道是否有办法扩展而不是修改和重新编译整个DLL? – VulgarBinary

+1

您将不得不重新编译该DLL。您可以访问[EF codeplex网站](http://entityframework.codeplex.com/discussions)并直接与EF团队讨论这一贡献 - 他们可能已经为此功能设计了一些高级设计并与您分享。 –

+3

投票过滤包括[这里](https://entityframework.codeplex.com/workitem/47)! – Chris

相关问题