2010-08-11 66 views
4

我一直在看下面的帖子,並試圖將其應用到礦山,但沒有運氣: LINQ Inner-Join vs Left-Join無法離開JOIN linq查詢工作!

我有以下查詢將返回0條記錄,每次我運行它:

 var tasks = from tt in d.luProjectTaskTypes 
        join cbt in d.CostByTasks 
         on tt.ProjectTaskTypeID equals cbt.ProjectTaskTypeID into temp 
        from cbt in temp.DefaultIfEmpty() 
        where cbt.ProposalID == Convert.ToInt32(this.StateItems["PropNumber"]) || cbt.ProposalID == null 
        select new 
        { 
         ProposalId = (cbt.ProposalID == null ? Convert.ToInt32(this.StateItems["PropNumber"]) : cbt.ProposalID), 
         TaskId = tt.ProjectTaskTypeID, 
         CostByTaskId = (cbt.CostByTaskID == null ? 0 : cbt.CostByTaskID), 
         TypeOfWork = tt.ProjectTaskType, 
         AmountRequested = (cbt.AmountRequested == null ? 0 : cbt.AmountRequested), 
         CostShare = (cbt.CostShareAmount == null ? 0 : cbt.CostShareAmount) 
        }; 

其中luProjectTaskTypes是具有選項列表的查找表。我希望爲此表中的每個條目返回一條記錄,無論它是否在CostByTasks中匹配,但我總是得到0.我做錯了什麼?

UPDATE:

這是SQL是generating-

SELECT 
    (CASE 
     WHEN ([t1].[ProposalID]) IS NULL THEN @p1 
     ELSE [t1].[ProposalID] 
    END) AS [ProposalId], [t0].[ProjectTaskTypeID] AS [TaskId], 
    (CASE 
     WHEN ([t1].[CostByTaskID]) IS NULL THEN @p2 
     ELSE [t1].[CostByTaskID] 
    END) AS [CostByTaskId], [t0].[ProjectTaskType] AS [TypeOfWork], 
    (CASE 
     WHEN [t1].[AmountRequested] IS NULL THEN CONVERT(Decimal(33,4),@p3) 
     ELSE CONVERT(Decimal(33,4),[t1].[AmountRequested]) 
    END) AS [AmountRequested], 
    (CASE 
     WHEN [t1].[CostShareAmount] IS NULL THEN CONVERT(Decimal(33,4),@p4) 
     ELSE CONVERT(Decimal(33,4),[t1].[CostShareAmount]) 
    END) AS [CostShare] 
FROM [frgprop].[luProjectTaskType] AS [t0] 
LEFT OUTER JOIN [frgprop].[CostByTask] AS [t1] ON [t0].[ProjectTaskTypeID] = [t1].[ProjectTaskTypeID] 
WHERE ([t1].[ProposalID] = @p0) OR (([t1].[ProposalID]) IS NULL) 
+0

生成的SQL看起來像什麼? – 2010-08-11 22:36:17

+0

@Jon,SQL添加 – 2010-08-11 22:48:13

+0

正如你所看到的,它肯定會產生一個LEFT JOIN ...所以我建議你開始對SQL本身進行黑客攻擊,直到產生你想要的東西,然後嘗試將它轉換回LINQ。 – 2010-08-11 22:55:34

回答

2

不知道這是否會幫助,但你可以嘗試你的where子句移動到一起 -

var tasks = from tt in d.luProjectTaskTypes 
      join cbt in d.CostByTasks 
       on new {ptid = tt.ProjectTaskTypeID, pid = cbt.ProposalID } equals new { ptid = cbt.ProjectTaskTypeID, pid = Convert.ToInt32(this.StateItems["PropNumber"] } into temp 
      from cbt in temp.DefaultIfEmpty() 
      select new 
      { 
       ProposalId = (cbt.ProposalID == null ? Convert.ToInt32(this.StateItems["PropNumber"]) : cbt.ProposalID), 
       TaskId = tt.ProjectTaskTypeID, 
       CostByTaskId = (cbt.CostByTaskID == null ? 0 : cbt.CostByTaskID), 
       TypeOfWork = tt.ProjectTaskType, 
       AmountRequested = (cbt.AmountRequested == null ? 0 : cbt.AmountRequested), 
       CostShare = (cbt.CostShareAmount == null ? 0 : cbt.CostShareAmount) 
      }; 

你需要擔心檢查cbt.ProposalID == null,它應該產生這種SQL代替 -

... FROM [frgprop].[luProjectTaskType] AS [t0] 
    LEFT OUTER JOIN [frgprop].[CostByTask] AS [t1] ON [t0].[ProjectTaskTypeID] = [t1].[ProjectTaskTypeID] AND [t1].[ProposalID] = @p0 

更新: 下面是編譯的更新版本。一些小的變化使它工作。

var tasks = from tt in d.luProjectTaskTypes 
         join cbt in d.CostByTasks 
          on new {tt.ProjectTaskTypeID, ProposalID = Convert.ToInt32(this.StateItems["PropNumber"]) } equals new {cbt.ProjectTaskTypeID, cbt.ProposalID} into temp 
         from cbt in temp.DefaultIfEmpty() 
         select new 
         { 
          ProposalId = (cbt.ProposalID == null ? Convert.ToInt32(this.StateItems["PropNumber"]) : cbt.ProposalID), 
          TaskId = tt.ProjectTaskTypeID, 
          CostByTaskId = (cbt.CostByTaskID == null ? 0 : cbt.CostByTaskID), 
          TypeOfWork = tt.ProjectTaskType, 
          AmountRequested = (cbt.AmountRequested == null ? 0 : cbt.AmountRequested), 
          CostShare = (cbt.CostShareAmount == null ? 0 : cbt.CostShareAmount) 
         }; 
+0

看起來你有正確的想法,但它並沒有完全編譯。我繼續爲我的未來用戶添加一篇自己的帖子,對其進行修改。 – 2010-08-15 02:00:37

+0

這很好 - 只是讓我知道編譯錯誤在哪裏,我可以在這裏修復它,這樣就沒有重複的答案,正確的答案得到信任。我不會檢查編譯錯誤,因爲設置這些類型對我來說太過分了。或者你甚至可以自己編輯它,因爲你有超過2000的聲望。 – 2010-08-16 00:04:16

+1

好吧添加了我的更新版本。謝謝你的幫助! – 2010-08-16 19:05:05

2

您的問題是在WHERE子句

當你LEFT JOIN表,這很好,但如果你在LEFT-JOINED表上設置了標準,它基本上把它變成了一個INNER JOIN。你應該允許Nulls通過這個。

where cbt.ProposalID == Convert.ToInt32(this.StateItems["PropNumber"]) OR cbt.ProposalID is NULL 

我不知道怎麼樣爲NULL語法 - 也許必須db.null(field),等等 - 你必須檢查上;但這個概念是有效的。

+0

此外 - 您需要將其重新轉換爲* left * join。 – dave 2010-08-11 22:36:22

+0

我假設你的意思是添加'|| cbt.ProposalID == null'。我做了這個,但沒有記錄。我已經更新了我的LINQ查詢以反映這種變化,那是什麼意思? – 2010-08-11 22:43:47

+0

請注意,更簡單的方法是將where子句放入連接中:「from dbCostByTasks.Where(x => x.ProposalId == ...)中的cbt」 – 2010-08-11 23:00:03