2013-02-19 3 views
3

Используя технику, найденную в статье MSDN "How to: Perform Left Outer Joins (C# Programming Guide)", я попытался создать левое внешнее соединение в моем коде Linq. В статье упоминается использование метода DefaultIfEmpty для создания левого внешнего соединения из группового соединения. В принципе, он инструктирует программу включать результаты левой (первой) коллекции, даже если в правой коллекции нет результатов.Linq left external join not working

Способ выполнения этой программы, однако, он делает это так, как если бы внешнее соединение не было указано.

В нашей базе данных AgentProductTraining представляет собой набор курсов, которые наши агенты взяли. Обычно вы не можете ввести Course в соответствующую таблицу без ввода соответствующего значения в таблицу CourseMaterials. Однако иногда это может произойти, поэтому мы хотим убедиться, что мы возвращаем результаты, даже если Course указан в AgentProductTraining без соответствующей информации в CourseMaterials.

 var training = from a in db.AgentProductTraining 
         join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm 
         where 
          a.SymNumber == id 
          from m in apm.DefaultIfEmpty() 
          where m.EffectiveDate <= a.DateTaken 
          && ((m.TerminationDate > a.DateTaken) | (m.TerminationDate == null)) 
         select new 
            { 
             a.AgentProdTrainId, 
             a.CourseCode, 
             a.Course.CourseDescription, 
             a.Course.Partner, 
             a.DateTaken, 
             a.DateExpired, 
             a.LastChangeOperator, 
             a.LastChangeDate, 
             a.ProductCode, 
             a.Product.ProductDescription, 
             m.MaterialId, 
             m.Description, 
             a.Method 
            }; 
+0

Есть навигационное свойство 'AgentProductTraining.CourseMaterials'? –

+0

Кроме того, название говорит, что внутреннее соединение lleft не работает, но я предполагаю, что это внешнее соединение? На самом деле, на вашем посту не существует проблемы. –

+0

Хороший улов, спасибо. Я не верю, что у нас есть свойство навигации на 'CourseMaterials' – NealR

ответ

3

Пример MSDN использует новую переменную subpet:

var query = from person in people 
        join pet in pets on person equals pet.Owner into gj 
        from subpet in gj.DefaultIfEmpty() 
        select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) }; 

Таким образом, вы должны использовать свой собственный "subpet", я переписал код, используя submat переменную:

 var training = from a in db.AgentProductTraining 
         join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm 
         where 
          a.SymNumber == id 
          from submat in apm.DefaultIfEmpty() 
          where 
          (submat.EffectiveDate <= a.DateTaken || submat.EffectiveDate == null) && 
          (submat.TerminationDate > a.DateTaken || submat.TerminationDate == null) 
         select new 
            { 
             a.AgentProdTrainId, 
             a.CourseCode, 
             a.Course.CourseDescription, 
             a.Course.Partner, 
             a.DateTaken, 
             a.DateExpired, 
             a.LastChangeOperator, 
             a.LastChangeDate, 
             a.ProductCode, 
             a.Product.ProductDescription, 
             MaterialId = (submat==null?-1:submat.MaterialId), 
             Description = (submat==null?String.Empty:submat.Description), 
             a.Method 
            }; 
+0

По какой-то причине я получаю следующее сообщение об ошибке в разделе« Результаты »раздела переменной« training »(нет подсказки, почему, в настоящее время изучая его)' The cast для значения типа «Int32» не удалось, поскольку материализованное значение равно null. Либо общий параметр типа результата, либо запрос должен использовать тип с нулевым значением. « – NealR

+0

Я предполагаю, что' submat.MaterialId' не может быть нулевым, поэтому вам нужно будет установить значение по умолчанию в случае, если внешнее соединение возвращает null (когда для материала AgentProductTraining нет материала CourseMaterials). Я отредактирую код, чтобы установить -1 в этом случае. –

+0

Извините ... VS2010 не понравилось. Я получаю сообщение 'Invalid anonymous type member declarator. Члены анонимного типа должны быть declaure с назначением члена, простым именем или доступом к члену. – NealR