SQL -> LINQ (C #) - PullRequest
       2

SQL -> LINQ (C #)

0 голосов
/ 29 марта 2012

У меня есть SQL-запрос (ниже), который по сути берет студента из tbStudents, а затем получает самый последний термин (число, но хранится как строку) в tbTerms.

Существует отношение один-ко-многим со студентом в tbStudents к записи семестра в tbTerms. Пример:

tbStudents:

StudentId FirstName LastName
12345     John      Smith
12346     Jane      Doe

tbTerms:

StudentId Term
12345     1234
12345     1235
12345     1236
12346     1233
12346     1234

Желаемая:

StudentId FirstName LastName Term
12345     John      Smith    1236
12346     Jane      Doe      1234

SQL-запрос:

select tbStudents.student_id, tbStudents.user_id, tbStudents.firstname, tbStudents.lastname, v.rTerm
    from  tbStudents
    inner join (
        select tbTerms.student_id, MAX(tbTerms.term) as rTerm
        from tbTerms
        group by tbTerms.student_id
    ) v on v.student_id = tbStudents.student_id

Я пытался объединить все это в одно утверждение LINQ, но у меня возникли проблемы. Есть ли способ сделать это в одном утверждении? Или это должно быть сделано в нескольких заявлениях. Спасибо заранее.

Редактировать: C # код того, что я пробовал.

var students = (from s in dockDb.tbStudents
                join t in dockDb.tbTerms on s.student_id equals t.student_id
                into pairs
                from p in pairs
                select new { UserId = s.user_id, StudentId = s.student_id, Term = p.term } ).ToList();

Вывод похож на:

StudentId FirstName LastName Term
12345     John      Smith    1234
12345     John      Smith    1235
12345     John      Smith    1236
12346     Jane      Doe      1233
12346     Jane      Doe      1234

Редактировать # 2: я использую Entity Framework для данных. Я не уверен, влияет ли это на что-то, но большинство решений «синтаксически некорректны», когда я пытаюсь их использовать.

Ответы [ 4 ]

1 голос
/ 29 марта 2012

Вы должны попробовать что-то вроде этого:

from s in dockDb.tbStudents
join t in dockDb.tbTerms on t.student_id equals s.student_id into st
group st by New {StudentID = st.student_id, Term = t.term} into g
select New { g.Key, g.Max(i => i.Term) }
0 голосов
/ 29 марта 2012

Groupby - твой друг.Давайте просто сгруппируем данные по идентификатору студента, а затем проецируем в новую форму.Это пример linqpad:

void Main()
{
    var students = new List<Student>()
    {
      new Student() { StudentID = 12345, Name = "Smith" },
      new Student() { StudentID = 12346, Name = "Jones" }
      };

    var terms = new List<Term>()
    {
        new Term() { StudentID=12345, TermID = 1234 },
        new Term() { StudentID=12345, TermID = 1235 },
        new Term() { StudentID=12345, TermID = 1236 },
        new Term() { StudentID=12345, TermID = 1237 },
        new Term() { StudentID=12346, TermID = 1233 },
        new Term() { StudentID=12346, TermID = 1234 },
    };

    var result = terms.GroupBy (tm => tm.StudentID)
                      .Select (gr => new
    {
        Name = students.First (s => s.StudentID == gr.Key).Name,
        Terms = gr.Select (g => g.TermID)
    });


    result.Dump();

}

// Define other methods and classes here
    public class Student
    {
        public int StudentID { get; set; }
        public string Name { get; set; }
    }

    public class Term
    {
        public int StudentID { get; set; }
        public int TermID { get; set; }
    }

Вот вывод, который можно использовать:

enter image description here

0 голосов
/ 29 марта 2012

Должно быть возможно. Попробуйте это:

from s in Students
join t in Terms on t.StudentId = s.StudentId
select new {Student = s, Term = t}
group by s into g
select new {g.Key.StudentId, g.Key.FirstName, g.Key.LastName, g.Max(x=>x.Term.term)};

Разбивая его, первые две строки определяют домен для поиска; а именно, внутренне объединенная комбинация студентов и терминов, связанная с помощью StudentId. Каждая уникальная комбинация Student и Term помещается в анонимный тип, а затем эти экземпляры группируются каждым уникальным Student в Lookup (доступная только для чтения коллекция IEnumerables, на которую ссылается ключ). Мы можем выбрать жизненно важную информацию ключа (студента) и найти в списке терминов слово с наибольшим значением (которое будет самым последним).

0 голосов
/ 29 марта 2012

Почему-то я всегда считал синтаксис с методами расширения более читабельным и естественным для написания. Итак, вот что:

context.Students.Select(s => new
{
    s.StudentId,
    s.FirstName,
    s.LastName,
    Term = context.Terms.Where(t => t.StudentId == s.StudentId)
                        .Select(t => t.TermNumber)
                        .OrderByDescending(t => t)
                        .First()
});

По сути, для каждого учащегося он выбирает все его / ее термины, упорядочивает их от самого последнего к наименее последнему и включает первый (самый последний) результат.

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