LINQ: запрос двух таблиц в одном запросе - PullRequest
0 голосов
/ 20 марта 2019

Простая структура сущности DbContext:

class SchoolDbContext : DbContext
{
    public DbSet<Teacher> Teachers {get; set;}
    public DbSet<Student> Students {get; set;}
}

Требование Дайте мне количество учителей и количество учеников.

Или, немного более сложным: «Дайте мне имена всех Учителей и дайте мне дни рождения всех Студентов»

Обычно для этого требуется два запроса.Согласно следующим ответам это можно сделать с помощью SQL в одном запросе:

Ответы такие:

SELECT id, startdate, enddate , '-' AS point_id 
FROM sarcshiftcentertable 
UNION
SELECT id, startdate, enddate, point_id 
FROM sarcshiftpointtable 

Но возможно ли сделать что-то подобное, используя LINQ в одном запросе?

Ответы указывают мне в направлении Queryable.Union .Однако эта функция ожидает для обеих коллекций один и тот же тип ввода.

Поэтому перед объединением следует выбрать что-то общее, что в данном случае равно object

var result = dbContext.Teachers.Select(teacher => teacher.Name).Cast<object>()
    .Union(dbContext.Students.Select(student => student.BirthDay).Cast<object>())
    // TODO select?

Теперь каждый DateTimeв последовательности день рождения студентов.Каждая строка является именем Учителя.

Другая возможность состоит в том, чтобы выбрать новый класс:

var result = dbContext.Teachers.Select(teacher => new
{
    TeacherName = teacher.Name,
    StudentBirthDay = null,
})
.Union(dbContext.Students.Select(student => new
{
     TeacherName = null,
     StudentBirthDay = student.BirthDay,
}))
// TODO: select?

. Теперь я могу определить, является ли Item TeacherName или StudentBirthDay, проверив,другое свойство равно нулю.

Но как продолжить?Как получить один объект, например:

new
{
    TeacherNames = ...
    StudentBirthdays = ...
}

или

new
{
    TeacherCount = ...
    StudentCount = ...
}

1 Ответ

0 голосов
/ 20 марта 2019

При асинхронном подходе это может быть гораздо более простой задачей и, возможно, более эффективной

async Task<IEnumerable<string>> GetTeacherNames()
{
    using (var context = CreateContext(fromConfiguration))
    {
        return await context.Teachers.Select(teacher => teacher.Name).ToListAsync();
    }
}

async Task<IEnumerable<DateTime>> GetStudentsBirthdays()
{
    using (var context = CreateContext(fromConfiguration))
    {
        return await context.Students.Select(student => student.BirthDay).ToListAsync();
    }
}

Использование

var teacherTask = GetTeacherNames();
var studentsTask = GetStudentsBirthdays();

await Task.WhenAll(teacherTask, studentsTask);

var allTeacherNames = teacherTask.Result;
var allStudentsBirthdays = studentsTask.Result;

Если запрос учителя занимает, например, 2 секунды, а ученика - 3 секунды, два асинхронных запроса займут примерно 3 секунды.

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