查询多对多关系实体框架(做错了??)
Querying Many to Many relationships Entitty Framework (doing wrong?? )
我一直在研究这个主题,并找到了一种在我的项目中实现这个查询的方法,但我不确定这里是否有问题。请帮忙
总而言之,我创建了这样的实体:
class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public ICollection<Courses> Courses {get;set;} //or public List <Courses> {get;set;}
}
class Course
{
public int CourseId { get; set; }
public string Name { get; set; }
public ICollection<Students> Students {get;set;} //or public List<Students> {get;set;}
}
// We can see here that the database creates the Join Table Correctly
我想做的事情:
在网格视图中显示每个学生,并为每个学生显示他们注册的课程。
如果我做了一个简单的查询,比如
dbContex.Students.ToList();
我们查看列表中的 Collection of courses 值为空。这里发生了什么?EF 不应该映射它并查询 SQL 以获取信息吗?
在此之后你无法解决问题,因为我发现的信息使用的是框架的其他方法(我认为是 Diagram First)并且他们在实体图中设置了一些东西。
我是如何解决这个问题的:
在 Wordpress Post 中找到一个我没有尝试过的查询,然后添加一些其他代码行来实现我想要的:
aux_S = contexto.Students.ToList();
foreach(var element in aux_S)
{
element.Courses= contexto.Courses.Where(c => c.Students.Any(s => s.StudentId == element.StudentId)).ToList();
}
// 我知道我可以做一个投影来忽略所有我不需要的字段,这只是为了尝试一下
我这样做错了吗?
成功了,但怎么可能呢?
您没有延迟加载,如果您添加 virtual
如下:public virtual ICollection<Courses> Courses {get;set;}
您应该加载课程。
但是,我建议使用延迟加载,因为它可能会导致性能问题,你想要做的是预加载。
所以当你查询你的学生时,你只需这样做:
dbContex.Students.Include(c => c.Courses).ToList();
数据库查询中速度较慢的部分之一是将数据传输到您的计算机。因此,最好只传输您计划使用的数据。
当您在 entity framework 中使用 LINQ 时,使用 Queryable.Select 是准确指定要传输的数据的好方法。这通常在您最终的 ToList / ToDictionary / FirstOrDefault / Single / ...
之前完成
您想要所有学生,每个学生都有他的所有课程。如果您查看您的表格,您会发现表格中的数据比您想要的多。例如,每个学生都有一个 Id,他的每个课程都有相同的 StudentId 值。因此,如果一个学生参加了 20 门课程,您将传输相同的 StudentId 值 21 次。
因此,为了使您的查询更高效:Select 仅包含您计划使用的学生的属性,以及您感兴趣的这些学生的课程的属性。
这将自动解决您的问题:
var result = myDbcontext.Students
// if you don't want all Students, use a Where:
.Where(student => student.City = "Guadalajara")
// Select only the properties you plan to use:
.Select(student => new
{
Id = student.Id,
Name = student.Name,
Birthday = student.Birthday,
Address = new
{
Street = student.Street,
City = student.City,
...
}
Courses = student.Courses
// if you don't want all courses: use a where
.Where(course => course.Start.Year == 2018)
// again: select only the properties you plan to use
{
Name = course.Name,
Location = course.Location,
...
// One of the useless properties to transfer:
// StudentId = course.StudentId
})
.ToList();
});
如果执行此查询:
var studentslist = dbContex.Students.ToList();
studentslist 上的每个项目都会有 'Courses' 集合 null,因为尽管 connection/relation 存在(在每个 table 之间),但您没有指定您想要那个集合人口稠密。为此,您可以相应地更改您的查询:
var studentslist = dbContex.Students.Include(p => p.Courses).ToList();
现在,在 运行 最后一次查询之后,如果您在 one/any 项上得到一个空列表,则意味着这些项(学生)未链接到任何课程。
我一直在研究这个主题,并找到了一种在我的项目中实现这个查询的方法,但我不确定这里是否有问题。请帮忙
总而言之,我创建了这样的实体:
class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public ICollection<Courses> Courses {get;set;} //or public List <Courses> {get;set;}
}
class Course
{
public int CourseId { get; set; }
public string Name { get; set; }
public ICollection<Students> Students {get;set;} //or public List<Students> {get;set;}
}
// We can see here that the database creates the Join Table Correctly
我想做的事情:
在网格视图中显示每个学生,并为每个学生显示他们注册的课程。
如果我做了一个简单的查询,比如
dbContex.Students.ToList();
我们查看列表中的 Collection of courses 值为空。这里发生了什么?EF 不应该映射它并查询 SQL 以获取信息吗?
在此之后你无法解决问题,因为我发现的信息使用的是框架的其他方法(我认为是 Diagram First)并且他们在实体图中设置了一些东西。
我是如何解决这个问题的:
在 Wordpress Post 中找到一个我没有尝试过的查询,然后添加一些其他代码行来实现我想要的:
aux_S = contexto.Students.ToList();
foreach(var element in aux_S)
{
element.Courses= contexto.Courses.Where(c => c.Students.Any(s => s.StudentId == element.StudentId)).ToList();
}
// 我知道我可以做一个投影来忽略所有我不需要的字段,这只是为了尝试一下
我这样做错了吗?
成功了,但怎么可能呢?
您没有延迟加载,如果您添加 virtual
如下:public virtual ICollection<Courses> Courses {get;set;}
您应该加载课程。
但是,我建议使用延迟加载,因为它可能会导致性能问题,你想要做的是预加载。
所以当你查询你的学生时,你只需这样做:
dbContex.Students.Include(c => c.Courses).ToList();
数据库查询中速度较慢的部分之一是将数据传输到您的计算机。因此,最好只传输您计划使用的数据。
当您在 entity framework 中使用 LINQ 时,使用 Queryable.Select 是准确指定要传输的数据的好方法。这通常在您最终的 ToList / ToDictionary / FirstOrDefault / Single / ...
之前完成您想要所有学生,每个学生都有他的所有课程。如果您查看您的表格,您会发现表格中的数据比您想要的多。例如,每个学生都有一个 Id,他的每个课程都有相同的 StudentId 值。因此,如果一个学生参加了 20 门课程,您将传输相同的 StudentId 值 21 次。
因此,为了使您的查询更高效:Select 仅包含您计划使用的学生的属性,以及您感兴趣的这些学生的课程的属性。
这将自动解决您的问题:
var result = myDbcontext.Students
// if you don't want all Students, use a Where:
.Where(student => student.City = "Guadalajara")
// Select only the properties you plan to use:
.Select(student => new
{
Id = student.Id,
Name = student.Name,
Birthday = student.Birthday,
Address = new
{
Street = student.Street,
City = student.City,
...
}
Courses = student.Courses
// if you don't want all courses: use a where
.Where(course => course.Start.Year == 2018)
// again: select only the properties you plan to use
{
Name = course.Name,
Location = course.Location,
...
// One of the useless properties to transfer:
// StudentId = course.StudentId
})
.ToList();
});
如果执行此查询:
var studentslist = dbContex.Students.ToList();
studentslist 上的每个项目都会有 'Courses' 集合 null,因为尽管 connection/relation 存在(在每个 table 之间),但您没有指定您想要那个集合人口稠密。为此,您可以相应地更改您的查询:
var studentslist = dbContex.Students.Include(p => p.Courses).ToList();
现在,在 运行 最后一次查询之后,如果您在 one/any 项上得到一个空列表,则意味着这些项(学生)未链接到任何课程。