C# 按实体框架分析查询

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();

我正在学习实体框架,我需要一些解释

让我们假设我已经创建了一些多对多关系,这样我们就有了表学生和课程,每种类型的实体可以有许多其他类型的实体

接下来,我有一个gridview,我想在其中显示一个表,其中有两列描述学生的姓名和他分配给的所有课程。为此,在我的WebForm的Page_Load事件中,我有以下代码:

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语句发生在内存中。