在多对多的例子里面我们做了三个表 Student, Course, StudentCourse, 并且用下面的代码添加了一些数据
public void InitData()
{
using (var dbContext = this.dbContextFactory.CreateDbContext())
{
if (dbContext.Students.Count() < 1)
{
var courses = GetCourses();
dbContext.AddRange(courses);
dbContext.SaveChanges();
var students = GetStudents();
dbContext.AddRange(students);
dbContext.SaveChanges();
var studentCourse1 = new StudentCourse()
{
StudentId = 1,
CourseId = 1,
};
var studentCourse2 = new StudentCourse()
{
StudentId = 1,
CourseId = 2,
};
var studentCourse3 = new StudentCourse()
{
StudentId = 2,
CourseId = 1,
};
dbContext.AddRange(studentCourse1, studentCourse2, studentCourse3);
dbContext.SaveChanges();
}
}
}
private static List<Course> GetCourses()
{
var course1 = new Course() { Name = "英语" };
var course2 = new Course { Name = "足球" };
return new List<Course>() { course1, course2 };
}
private static List<Student> GetStudents()
{
var student1 = new Student() { Name = "张三", };
var student2 = new Student() { Name = "李四", };
return new List<Student>() { student1, student2 };
}
我们给 课程表加了两条数据 英语 足球 我们给 学生表加了两条数据张三 李四 张三报了两个课程 英语 足球 李四 只报了一个课程 英语
这样就可以用下面的语句来查询了
public void GetStudentWithCourses()
{
var scQuery = from s in malemaDbContext.Students
join sc in malemaDbContext.StudentCourses
on s.Id equals sc.StudentId
select new { s.Name, sc.CourseId };
var query2 = from sc in scQuery
join c in malemaDbContext.Courses
on sc.CourseId equals c.Id
select new { sc.Name, courseName = c.Name };
query2.ToList();
//使用 预先加载 eager loading
var student = this.malemaDbContext.Students.Include(x => x.StudentCourses)
.ThenInclude(x => x.Course);
}
生成的sql语句如下
--第一个生成的sql的语句
SELECT [s].[Name], [c].[Name] AS [courseName]
FROM [Students] AS [s]
INNER JOIN [StudentCourses] AS [s0] ON [s].[Id] = [s0].[StudentId]
INNER JOIN [Courses] AS [c] ON [s0].[CourseId] = [c].[Id]
-- 第二个生成的sql语句
SELECT [s].[Id], [s].[Name], [t].[Id], [t].[CourseId], [t].[StudentId], [t].[Id0], [t].[Name]
FROM [Students] AS [s]
LEFT JOIN (
SELECT [s0].[Id], [s0].[CourseId], [s0].[StudentId], [c].[Id] AS [Id0], [c].[Name]
FROM [StudentCourses] AS [s0]
INNER JOIN [Courses] AS [c] ON [s0].[CourseId] = [c].[Id]
) AS [t] ON [s].[Id] = [t].[StudentId]
ORDER BY [s].[Id], [t].[Id], [t].[Id0]
public void GetCourseWithStudents()
{
var students = this.malemaDbContext.Courses.Include(x => x.StudentCourses)
.ThenInclude(x => x.Student).ToList();
}
生成的sql语句如下
SELECT [c].[Id], [c].[Name], [t].[Id], [t].[CourseId], [t].[StudentId], [t].[Id0], [t].[Name]
FROM [Courses] AS [c]
LEFT JOIN (
SELECT [s].[Id], [s].[CourseId], [s].[StudentId], [s0].[Id] AS [Id0], [s0].[Name]
FROM [StudentCourses] AS [s]
INNER JOIN [Students] AS [s0] ON [s].[StudentId] = [s0].[Id]
) AS [t] ON [c].[Id] = [t].[CourseId]
ORDER BY [c].[Id], [t].[Id], [t].[Id0]
sql查询出来的原始结果如下
但是linq出来的是两条记录,不是三条哦。符合我们的预期
从上面的例子我们可以看出借助Include我们可以很方便的进行一些查询了。
上面的完整代码可以在分支querying/many_to_many
看到
git clone https://gitee.com/malema/Examples
git checkout querying/many_to_many
ManyToManyExample.cs