实体框架 - 投影查询


实体的 LINQ

理解 LINQ to Entities 的最重要概念之一是它是一种声明性语言。重点是定义您需要什么信息,而不是如何获取信息。

  • 这意味着您可以花更多的时间处理数据,而用更少的时间尝试找出执行访问数据库等任务所需的底层代码。

  • 重要的是要理解声明性语言实际上并没有消除开发人员的任何控制权,但它可以帮助开发人员将注意力集中在重要的事情上。

LINQ to Entities 基本关键字

了解用于创建 LINQ 查询的基本关键字非常重要。只需要记住几个关键字,但您可以通过各种方式将它们组合起来以获得特定的结果。以下列表包含这些基本关键字并提供每个关键字的简单描述。

先生。没有。 关键字和描述
1

上升

指定从范围的最小(或最低)元素到范围的最高元素进行排序操作。这通常是默认设置。例如,当执行字母顺序排序时,排序将在从 A 到 Z 的范围内。

2

经过

指定用于实现分组的字段或表达式。字段或表达式定义用于执行分组任务的键。

3

降序

指定从范围的最大(或最高)元素到范围的最低元素进行排序操作。例如,当执行字母排序时,排序将在从 Z 到 A 的范围内。

4

等于

在连接语句的左右子句之间使用,将主上下文数据源连接到辅助上下文数据源。equals 关键字左侧的字段或表达式指定主数据源,而 equals 关键字右侧的字段或表达式指定辅助数据源。

5

指定用于获取所需信息的数据源并定义范围变量。该变量与循环中用于迭代的变量具有相同的用途。

6

团体

使用您指定的键值将输出组织为组。使用多个组子句创建多个级别的输出组织。组子句的顺序决定了特定键值在分组顺序中出现的深度。您可以将此关键字与 by 结合起来创建特定的上下文。

7

有多种用途。在这种情况下,关键字确定用于查询的上下文数据库源。使用联接时,in 关键字用于用于联接的每个上下文数据库源。

8

进入

指定可用作 LINQ 查询子句(例如 join、group 和 select)的引用的标识符。

9

加入

从两个相关数据源创建单个数据源,例如在主/详细信息设置中。连接可以指定内部连接、组连接或左外部连接,默认情况下内部连接。您可以在msdn.microsoft.com上阅读有关联接的更多信息

10

定义一个范围变量,可用于存储查询表达式中的子表达式结果。通常,范围变量用于提供附加的枚举输出或提高查询的效率(以便特定任务(例如查找字符串的小写值)不需要执行多次)。

11

指定用于实现连接的字段或表达式。字段或表达式定义两个上下文数据源所共有的元素。

12

奥德比

为查询创建排序顺序。您可以添加升序或降序关键字来控制排序顺序。使用多个 orderby 子句创建多个级别的排序。orderby 子句的顺序决定了排序表达式的处理顺序,因此使用不同的顺序将导致不同的输出。

13

在哪里

定义 LINQ 应从数据源检索什么。您可以使用一个或多个布尔表达式来定义要检索的内容的细节。布尔表达式使用 && (AND) 和 || 相互分隔。(或)运算符。

14

选择

通过指定要返回的信息来确定 LINQ 查询的输出。该语句定义 LINQ 在迭代过程中返回的元素的数据类型。

投影

投影查询通过仅从数据库中检索特定字段来提高应用程序的效率。

  • 获得数据后,您可能需要根据需要对其进行投影或过滤,以在输出之前调整数据。

  • 任何 LINQ to Entities 表达式的主要任务都是获取数据并将其作为输出提供。

本章的“开发 LINQ to Entities 查询”部分演示了执行此基本任务的技术。

让我们看一下下面的代码,其中将检索学生列表。

using (var context = new UniContextEntities()) {

   var studentList = from s in context.Students select s;

   foreach (var student in studentList) {
      string name = student.FirstMidName + " " + student.LastName;
      Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
   }
}

单个对象

要检索单个学生对象,您可以使用 First() 或 FirstOrDefault 可枚举方法,它返回序列的第一个元素。First 和 FirstOrDefault 之间的区别在于,如果没有符合所提供条件的结果数据,First() 将引发异常,而如果没有结果数据,FirstOrDefault() 将返回默认值 null。在下面的代码片段中,将检索列表中第一个名字为 Ali 的学生。

using (var context = new UniContextEntities()) {

   var student = (from s in context.Students where s.FirstMidName 
      == "Ali" select s).FirstOrDefault<Student>();

   string name = student.FirstMidName + " " + student.LastName;
   Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
}

您还可以使用 Single() 或 SingleOrDefault 获取单个学生对象,该对象返回序列的单个特定元素。在以下示例中,检索 ID 为 2 的单个学生。

using (var context = new UniContextEntities()) {

   var student = (from s in context.Students where s.ID 
      == 2 select s).SingleOrDefault<Student>();
   string name = student.FirstMidName + " " + student.LastName;
	
   Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
   Console.ReadKey();
}

对象列表

如果你想检索名字是 Ali 的学生列表,那么你可以使用 ToList() 枚举方法。

using (var context = new UniContextEntities()) {

   var studentList = (from s in context.Students where s.FirstMidName 
      == "Ali" select s).ToList();

   foreach (var student in studentList) {
      string name = student.FirstMidName + " " + student.LastName;
      Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
   }

   Console.ReadKey();
}

命令

要以任何特定顺序检索数据/列表,您可以使用 orderby 关键字。在以下代码中,将按升序检索学生的片段列表。

using (var context = new UniContextEntities()) {

   var studentList = (from s in context.Students orderby
      s.FirstMidName ascending select s).ToList();

   foreach (var student in studentList) {
      string name = student.FirstMidName + " " + student.LastName;
      Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
   }

   Console.ReadKey();
}

标准与投影实体框架查询

假设您有一个包含 ID、FirstMidName、LastName 和 EnrollmentDate 的 Student 模型。如果您想返回学生列表,标准查询将返回所有字段。但如果您只想获取包含 ID、FirstMidName 和 LastName 字段的学生列表。这是您应该使用投影查询的地方。以下是投影查询的简单示例。

using (var context = new UniContextEntities()) {

   var studentList = from s in context.Students
      orderby s.FirstMidName ascending
      where s.FirstMidName == "Ali"

   select new {s.ID, s.FirstMidName, s.LastName};

   foreach (var student in studentList) {
      string name = student.FirstMidName + " " + student.LastName;
      Console.WriteLine("ID : {0}, Name: {1}", student.ID, name);
   }

   Console.ReadKey();
}

上面的投影查询不包括 EnrollmentDate 字段。这将使您的申请更快。