LINQ:在一个查询中查询两个表

时间:2019-03-20 08:54:15

标签: entity-framework linq

一个简单的实体框架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?

现在,我可以通过检查其他属性是否等于null来检测某项是TeacherName还是StudentBirthDay。

但是如何继续?我如何得到一个像这样的物体:

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

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

1 个答案:

答案 0 :(得分:0)

使用异步方法,这可能是一件容易的事,而且可能更高效

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秒。