2015-04-01 109 views
1

所以我有以下的Linq查詢:EF Linq查詢使用條件包括:

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

這將返回一個會員單位,擁有一組有一個項目子MemberProjects的。我想限制會員項目僅限於項目子項目爲 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子句中的表達。

如何做到這一點的任何想法將是巨大的:)

+0

如果MemberProject有一個引用返回到它的包含成員,也許你可以用MemberProjects來啓動查詢嗎? – 2015-04-01 04:26:13

回答

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的this post關於ORM的多對多關係。

更新

我想出了這個用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(); 

20毫秒下後始終返回VS另外一個徘徊在60毫秒(如果這對你很重要)。

我希望這會有所幫助。