2010-08-11 43 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