实体框架 - 投影查询



LINQ to Entities

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

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

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

LINQ to Entities 核心关键字

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

序号 关键字及描述
1

升序

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

2

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

3

降序

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

4

等于

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

5

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

6

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

7

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

8

指定一个标识符,您可以将其用作 LINQ 查询子句(如联接、组和选择)的参考。

9

联接

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

10

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

11

指定用于实现联接的字段或表达式。字段或表达式定义一个对两个上下文数据源都通用的元素。

12

排序依据

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

13

哪里

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

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,如果为提供的条件没有结果数据。

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 字段。这将使您的应用程序更快。

广告