【问题标题】:Can't get Left JOIN linq query to work!无法让 Left JOIN linq 查询工作!
【发布时间】:2011-03-28 15:50:27
【问题描述】:

我一直在查看以下帖子并尝试将其应用于我的帖子,但没有运气: LINQ Inner-Join vs Left-Join

下面的查询每次运行都会返回 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。我做错了什么?!

更新:

这是它正在生成的 SQL-

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)

【问题讨论】:

  • 生成的SQL是什么样的?
  • 如您所见,它肯定会生成 LEFT JOIN...所以我建议您开始对 SQL 本身进行破解,直到产生您想要的结果,然后尝试将其转换回 LINQ。

标签: .net linq linq-to-sql


【解决方案1】:

不确定这是否有帮助,但您可以尝试将 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)
                        };

【讨论】:

  • 看起来你有正确的想法,但它并没有完全编译。我继续添加了我自己的帖子,其中包含为未来用户所做的工作更改。
  • 没关系 - 只要让我知道编译错误在哪里,我可以在这里修复它,这样就没有重复的答案并且正确的答案得到了认可。我不打算检查编译错误,因为设置类型对我来说太过分了。或者您甚至可以自己编辑它,因为您拥有超过 2000 名声望。
【解决方案2】:

您的问题出在 WHERE 子句中

当您 LEFT JOIN 一个表时,这很好,但是如果您在 LEFT-JOINED 表上设置标准,它基本上会将它变成一个 INNER JOIN。您应该允许 Null 越过这一点。

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

我不确定 is NULL 语法怎么样——也许必须是 db.null(field) 等等——你必须检查一下;但这个概念是有效的。

【讨论】:

  • 另外——你需要把它转回一个left连接。
  • 我假设您的意思是添加|| cbt.ProposalID == null。我这样做了,但仍然没有记录。我已经更新了我的 LINQ 查询以反映这一变化,这就是你的意思吗?
  • 请注意,更简单的方法是将 where 子句放入连接中:“from cbt in d.CostByTasks.Where(x => x.ProposalId == ...)”
  • Arg... 是的——这就是我的意思。我在常规 SQL 查询中一直看到这个问题。好的——还在寻找。我想接下来我会尝试关闭 WHERE 子句,看看你的左连接是否正常工作——至少这可以帮助缩小范围。
  • 我还建议您在 this.StateItems["PropNumber"] 上执行 response.write,以确保您 认为 的值确实存在。 ..
猜你喜欢
  • 1970-01-01
  • 2015-05-25
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 2018-02-21
  • 2015-06-29
相关资源
最近更新 更多