2010-08-11 7 views
4

que je cherchais au poste et essayer la suite de l'appliquer à la mienne, mais sans succès: LINQ Inner-Join vs Left-JoinImpossible d'obtenir la requête Left JOIN linq pour fonctionner!

J'ai la requête ci-dessous qui retourne 0 enregistrements à chaque fois que je le lance:

 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 est une table de recherche qui a une liste d'options. Je veux un enregistrement retourné pour chaque entrée dans cette table indépendamment de savoir si elle a un match dans CostByTasks mais je reçois toujours 0. Qu'est-ce que je fais mal ?!

MISE À JOUR:

Ceci est le SQL est 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

À quoi ressemble le SQL généré? –

+0

@Jon, SQL ajouté –

+0

Comme vous pouvez le voir, il génère certainement un LEFT JOIN ... donc je vous suggère de commencer à pirater le SQL lui-même jusqu'à ce que cela produise ce que vous voulez, puis essayez de le convertir en LINQ. –

Répondre

2

Je ne sais pas si cela va aider, mais vous pouvez essayer de déplacer votre clause where dans la jointure -

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) 
      }; 

vous devez vous soucier de la vérification des cbt.ProposalID == null et il devrait produire ce sql au lieu -

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

MISE À jOUR: Voici la version mise à jour qui compile. Quelques changements mineurs l'ont fait fonctionner.

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

On dirait que vous avez la bonne idée, mais il ne compile pas tout à fait. Je suis allé de l'avant et ajouté un poste de mes propres avec des changements de travail pour les futurs utilisateurs. –

+0

C'est bien - faites le moi savoir où l'erreur de compilation est un je peux le réparer ici, de cette façon il n'y a aucune réponse en double et la bonne réponse obtient le crédit. Je n'allais pas vérifier les erreurs de compilation puisque la mise en place des types serait exagérée de ma part. Ou vous pouvez même l'éditer vous-même puisque vous avez plus de 2000 réputation. –

+1

D'accord a ajouté ma version mise à jour. Merci de votre aide! –

2

Votre problème est dans la clause WHERE

Lorsque vous LEFT JOIN une table, qui est très bien, mais si vous définissez des critères sur la table LEFT-JOINED, cela le transforme en INNER JOIN. Vous devriez permettre à Nulls de dépasser cela.

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

Je ne sais pas comment au sujet de la syntaxe est NULL - peut-être avoir à être db.null(field), etc. - vous devrez vérifier que; mais le concept est valide.

+0

Aussi - vous devez le réactiver en une jointure * left *. – dave

+0

Je suppose que vous voulez dire ajouter '|| cbt.ProposalID == null'. Je l'ai fait et toujours pas de dossiers. J'ai mis à jour ma requête LINQ pour refléter ce changement, c'est ce que vous vouliez dire? –

+0

Notez qu'une façon plus simple de le faire serait de mettre la clause where dans la jointure: "de cbt dans d.CostByTasks.Where (x => x.ProposalId == ...)" –