带有条件的EF Linq查询包括

时间:2015-04-01 03:37:00

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

所以我有以下Linq查询:

var member = (from mem in 
              context.Members.Include(m => 
              m.MemberProjects.Select(mp => mp.Project))
              where mem.MemberId == memberId
             select mem).FirstOrDefault();

这将返回一个Member实体,其中包含一组具有Project子项的MemberProjects。我想将MemberProjects限制为只有Project子项拥有属性的那些 ProjectIdParent == null

我失败的尝试之一可能会使意图更清晰:

var member = (from mem in context.Members
             .Include(m => m.MemberProjects
                            .Where(mp => 
                                   mp.Project.ProjectIdParent == null)
             .Select(proj => proj.Project))
             where mem.MemberId == memberId
             select mem).FirstOrDefault();

由于Where子句,这当然会引发Include表达式无效。

关于如何做到这一点的任何想法都会很棒:)

1 个答案:

答案 0 :(得分:0)

免责声明:我没有测试过这个。这只是一个想法。如果您让我知道结果,我会相应地更新。 (跳至测试解决方案的更新部分)

var member = (from mps in context.MemberProjects
                                .Include(m => m.Members)
                                .Include(m => m.Projects)  
              where mps.Project.ProjectIdParent == null
              select mps)
              .FirstOrDefault(mprojs => mprojs.Member.MemberId == memberId);     

我还会使用类似EFProfiler之类的内容来分析查询,以确保生成的查询不会离开理智领域。

你也可以看看Jimmy Bogard与ORMs的多对多关系this post

更新

我为EF 6.1.3提出了多种经过测试的解决方案。我的Edmx看起来如下:

enter image description here

设置数据如下:

enter image description here

我能够运行以下代码以正确获取MemberFive

var member = context.Members.FirstOrDefault
                     (m => m.MemberId == memberId 
                         && m.Projects.Any(p => p.ProjectParentId == null));

生成的SQL如下所示:

SELECT TOP (1) [Extent1].[MemberId]   AS [MemberId],
           [Extent1].[MemberName] AS [MemberName]
FROM   [dbo].[Members] AS [Extent1]
WHERE  ([Extent1].[MemberId] = 1)
   AND (EXISTS (SELECT 1 AS [C1]
                FROM   (SELECT [MemberProjects].[MemberId]  AS [MemberId],
                               [MemberProjects].[ProjectId] AS [ProjectId]
                        FROM   [dbo].[MemberProjects] AS [MemberProjects])     
           AS [Extent2]
                       INNER JOIN [dbo].[Projects] AS [Extent3]
                         ON [Extent3].[ProjectId] = [Extent2].[ProjectId]
                WHERE  ([Extent1].[MemberId] = [Extent2].[MemberId])
                       AND ([Extent3].[ProjectParentId] IS NULL)))

如果你不喜欢生成的查询,你可以使用它:

 var memberQuery = @"Select M.* from Members M
                            inner join MemberProjects MP on M.MemberId = Mp.ProjectId
                            inner join Projects P on MP.ProjectId = P.ProjectId
                            where M.MemberId = @MemberId and P.ProjectParentId is NULL";
 var memberParams = new[]
                     {
                      new SqlParameter("@MemberId", 1)
                     };
 var member3 = context.Members.SqlQuery(memberQuery, memberParams)
               .FirstOrDefault();

后者一直在20ms左右返回,而另一个在60ms左右徘徊(如果这对你很重要)。

我希望这会有所帮助。