C# 按实体框架分析查询
我正在学习实体框架,我需要一些解释 让我们假设我已经创建了一些多对多关系,这样我们就有了表学生和课程,每种类型的实体可以有许多其他类型的实体 接下来,我有一个gridview,我想在其中显示一个表,其中有两列描述学生的姓名和他分配给的所有课程。为此,在我的WebForm的Page_Load事件中,我有以下代码:C# 按实体框架分析查询,c#,sql,asp.net,entity-framework,linq,C#,Sql,Asp.net,Entity Framework,Linq,我正在学习实体框架,我需要一些解释 让我们假设我已经创建了一些多对多关系,这样我们就有了表学生和课程,每种类型的实体可以有许多其他类型的实体 接下来,我有一个gridview,我想在其中显示一个表,其中有两列描述学生的姓名和他分配给的所有课程。为此,在我的WebForm的Page_Load事件中,我有以下代码: protected void Page_Load(object sender, EventArgs e) { MyModel dbContext = new MyModel();
protected void Page_Load(object sender, EventArgs e)
{
MyModel dbContext = new MyModel();
GridView1.DataSource = from student in dbContext.Students
.Include("Courses").ToList()
select new
{
Name = student.StudentName,
Courses = string.Join(",", student.Courses.Select(c => c.CourseName))
};
GridView1.DataBind();
}
现在它可以工作了,但请注意,查询并不是真正按实体框架分析的,因为行:
GridView1.DataSource = from student in dbContext.Students.Include("Courses").ToList()
使此查询由LINQ对象提供程序分析。如果我不使用ToList方法,而是想写:
var query = from student in dbContext.Students.Include("Courses")
select new { ... };
GridView1.DataSource = query.ToList();
GridView1.DataBind();
然后我得到了一个例外,即实体框架无法识别连接方法。我可以接受这一点,但我想如果查询由EF的引擎分析,应用程序会运行得更快,对吗
如果是这样,我如何重写代码分配字符串到匿名类型的Courses属性以获得相同的结果?关于为什么Join不起作用。
代码
返回IQueryable。此时,您的数据尚未具体化=没有调用数据库来获取实体。这意味着,当稍后调用ToList=materialize实体时,查询中包含的所有内容都将转换为SQL。SQL对string.Join一无所知,这就是它抱怨的原因。第一个示例之所以有效,是因为LinqToObject是在C中执行的,而不是SQL,因此它知道如何处理string.Join
有关查询中可以和不能包含的内容的详细信息:
更新:
虽然这不是问题的一部分,但值得一提的是,您可能需要为数据实现分页。您不太可能同时在一个数据网格中显示成百上千个项目。搜索Take.关于为什么Join不起作用。
代码
返回IQueryable。此时,您的数据尚未具体化=没有调用数据库来获取实体。这意味着,当稍后调用ToList=materialize实体时,查询中包含的所有内容都将转换为SQL。SQL对string.Join一无所知,这就是它抱怨的原因。第一个示例之所以有效,是因为LinqToObject是在C中执行的,而不是SQL,因此它知道如何处理string.Join
有关查询中可以和不能包含的内容的详细信息:
更新:
虽然这不是问题的一部分,但值得一提的是,您可能需要为数据实现分页。您不太可能同时在一个数据网格中显示成百上千个项目。搜索Take。到目前为止,您所使用的方法唯一真正的问题是,如果要应用筛选,它将在调用ToList之后应用,也将在内存中应用。 我会把你的问题分成两部分。第一部分将从数据库读取数据,并允许您包含where子句,而第二部分将对象映射到格式中
protected void Page_Load(object sender, EventArgs e)
{
using (var dbContext = new MyModel())
{
var students = (from student in dbContext.Students
/*optional where clause*/
select new
{
Name = student.StudentName,
Courses = student.Courses.Select(c => c.CourseName)
}).ToList();
GridView1.DataSource = students.Select(s => new { s.Name, Courses = String.Join(",", s.Courses)}).ToList();
GridView1.DataBind();
}
}
值得一提的是,您可以使用Aggregate完全在EF中重新创建它,但我并不认为这是必要的。到目前为止,您这样做的唯一真正问题是,如果您想应用过滤,它将在调用ToList后应用,也将在内存中应用。 我会把你的问题分成两部分。第一部分将从数据库读取数据,并允许您包含where子句,而第二部分将对象映射到格式中
protected void Page_Load(object sender, EventArgs e)
{
using (var dbContext = new MyModel())
{
var students = (from student in dbContext.Students
/*optional where clause*/
select new
{
Name = student.StudentName,
Courses = student.Courses.Select(c => c.CourseName)
}).ToList();
GridView1.DataSource = students.Select(s => new { s.Name, Courses = String.Join(",", s.Courses)}).ToList();
GridView1.DataBind();
}
}
值得一提的是,您可以使用Aggregate完全在EF中重新创建此课程,但我并不认为这是必要的。我认为。IncludeCourses在这种情况下是多余的非常正确的-通过在调用ToList之前选择select子句中的课程名称,这是进行第一次数据库调用的时间,那么include调用就不是必需的了。@pawel你是用你的例子还是我的例子来获得NRE的?@pawel是的,include的目的是专门加载一个实体,但在我的例子中,课程的选择是在加载实体之前进行的。事实上,我们从不加载实体,只加载匿名类型。我认为。IncludeCourses在这种情况下是多余的非常正确-通过在调用ToList之前在select子句中选择课程名称,这是在第一次数据库调用时进行的,那么include调用就不是必需的了。@pawel您是使用您的示例还是我的示例获得NRE的?@pawel是,include的目的是专门加载实体,但在我的示例中,课程的选择发生在加载实体之前。事实上,我们从不加载实体,只加载匿名类型。此外,正确的处理方法是在一个查询中完成所有可以在SQL中完成的部分,包括where条件,然后是NUMRABLE,然后可以链接下一组Linq
语句发生在内存中。对此进行补充:正确的处理方法是在一个查询中完成所有可以在SQL中完成的部分,包括where条件,然后是NUMRABLE,然后可以链接下一组Linq语句发生在内存中。