2012-04-20 4 views
0

Я пытаюсь присоединиться к двум таблицам с отношением один к другому, но мне нужно только, чтобы данные столбца «один» отображались в одной строке, он должен быть нулевым во всех остальных строках (не важно который). Итак:Более эффективный LINQ JOIN

TEACHER 
--------- 
TeacherID 
TeacherBiography 
. 
. 
. 

STUDENT 
----------- 
TeacherID 
StudentFName 
StudentLName 
. 
. 
. 

Пример: Вы хотите, чтобы все студенты, Имя является «Джо», присоединиться к Учителю с помощью TeacherID, но ограничить возвращаемые результаты, так что данные Учитель не возвращается в каждой строке. Причина в том, что Учитель-биография велика; Мне нужно, чтобы оно вернулось, но не в каждой строке.

Таким образом, некоторые выходной образец должен выглядеть следующим образом:

------------------------------------------------ 
StudentFName | StudentLName | TeacherID | TeacherBiography 
------------------------------------------------ 
'Joe'  | 'Smith'  | 1   | 'long biography for teacher 1..' 
'Joe'  | 'Jones'  | 2   | 'long biography for teacher 2..' 
'Joe'  | 'Michaels' | 1   | null 
'Joe'  | 'Rogers'  | 3   | 'long biography for teacher 3..' 
'Joe'  | 'Washington' | 1   | null 
. 
. 
. 
. 

Таким образом, в случае Michaels и Вашингтоне TeacherBiograph (и все остальные столбцы учителя) равно нулю, так как данные уже вернулись в строке Смита.

Как это сделать?

-J

+2

«Более эффективный», чем что? – Magnus

+0

Извините, более эффективен, чем отправка одного и того же длинного столбца биографии много раз в результате работы с БД. – user1346563

ответ

0

Я думаю, что единственный эффективный способ сделать это, чтобы присоединиться STUDENT с и TEACHER сек с TeacherID в качестве ключа, то вы можете вывести этот ключ только один раз, только один ряд, а другой строки для того же ключа вывода null вместо этого, как это:

var StudentsList = students.Join( //Inner join 
    Teachers, 
    s => s.TeacherID, 
    t => t.TeacherID, 
    (teacher, teacherStudetns) => 
     new 
     { 
      Teacher = teacher, 
      HisStudents = teacherStudetns 
     }); 

Тогда вы можете выводить только один раз клавишу, например:

foreach(var item in StudentsList) 
{ 
    Console.Writline("Teach Name: {0}, His students:", item.TeacherBiography); 
    foreach(var student in item.HisStudents) 
    { 
     Console.writeLine("---------- {0}", student.StudentName); 
    } 
} 
+0

Если я чего-то не упускаю, это просто делает JOIN и по-прежнему отправляет большое количество дублирующего учителя обратно из БД. Я не пытаюсь эффективно печатать результаты, я пытаюсь эффективно получить результаты из БД. – user1346563

+0

@ user1346563, это не отображает большое количество дублирующих учителей из БД, оно будет в форме * teacher -> list students *, i. e .: у каждого преподавателя есть список учеников, и если вы используете LINQ to sql, ваш запрос будет выполняться в базе данных, и вы не будете в курсе об эффективности. Если вы хотите, чтобы ваш запрос получил список данных в форме, опубликованной в вашем вопросе, вы можете составить свой список вручную, итерации каждого ученика, чтобы получить его соответствующего учителя только для первого, добавьте «null» для остальных. и это сделает ваш запрос полностью неэффективным. –

+0

Независимо от красивой структуры реляционных объектов (учитель-> студенты), которые мы имеем в виду, в БД и в запросе, БД собирается отправить кучу «сплющенных» строк обратно клиенту, а не объекты-учителя указывая на студенческие объекты (по крайней мере, я думаю, это будет). Поэтому, когда он сглаживает их на стороне БД, чтобы отправить обратно клиенту, будет ли он дублировать столбцы учителя в каждой строке, где значение TeacherID одинаково?Когда я смотрю на результаты запроса в отладчике, похоже, что данные дублируются, но это может быть клиентская сторона драйвера БД «умная». – user1346563

0

Я бы сделал это за два шага, вместо того, чтобы усложнять ваш код, чтобы попытаться сделать это в одном. Во-первых, получить информацию о студенте, о которой вы заботитесь. После этого вы можете выполнить другой запрос, чтобы получить информацию о преподавателях, учитывая отдельный список TeacherID.

var students = //student query 
var teacherIds = students.Select(p => p.TeacherID).Distinct(); 
var teachers = teacherTable.Where(p => p.Contains(teacherIds)); 

После этого вы можете объединить два результата в памяти.

var allData = from s in students 
    join t in teachers on 
    t.teacherID equals s.TeacherID 
    select new { StudentName = s.Name, TeacherBio = t.TeacherBiography}; 

Это приведет к двум ударам базы данных, но вы вернете только те элементы данных, которые вам нужны.

+0

Да, я думал об этом, но, похоже, такая распространенная проблема (в какой-то степени это связано с какой-то проблемой), что должно быть простое решение с одним запросом? – user1346563

Смежные вопросы