Не удается заставить работать запрос LINQ Left! - PullRequest
4 голосов
/ 12 августа 2010

Я просматривал следующий пост и пытался применить его к моему, но безуспешно: LINQ Inner-Join против 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)

Ответы [ 2 ]

2 голосов
/ 12 августа 2010

Не уверен, поможет ли это, но вы можете попробовать перенести предложение 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

UPDATE: Ниже обновленная версия, которая компилируется. Несколько небольших изменений заставили его работать.

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)
                        };
2 голосов
/ 12 августа 2010

Ваша проблема в предложении WHERE

Когда вы ПРИСОЕДИНЯЕТЕСЬ К таблице, это нормально, но если вы установите критерии для таблицы LEFT-JOINED, она в основном превращает ее в INNER JOIN. Вы должны позволить Нулям пройти через это.

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

Я не уверен, как насчет синтаксиса NULL - возможно, он должен быть db.null(field) и т. Д. - вам придется проверить это; но концепция верна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...