LINQ – 快速指南

LINQ – 快速指南


LINQ – 概述

世界各地的开发者在查询数据时总是遇到问题,因为缺乏明确的路径,需要掌握多种技术,如SQL、Web Services、XQuery等。

LINQ(语言集成查询)在 Visual Studio 2008 中引入并由 Anders Hejlsberg 设计,即使不了解 SQL、XML 等查询语言,也可以编写查询。LINQ 查询可以针对不同的数据类型编写。

LINQ 查询示例

C#

using System;
using System.Linq;

class Program {
   static void Main() {
   
      string[] words = {"hello", "wonderful", "LINQ", "beautiful", "world"};
		
      //Get only short words
      var shortWords = from word in words where word.Length <= 5 select word;
	    
      //Print each word out
      foreach (var word in shortWords) {
         Console.WriteLine(word);
      }	 
		
      Console.ReadLine();
   }
}

VB

Module Module1
   Sub Main()
      Dim words As String() = {"hello", "wonderful", "LINQ", "beautiful", "world"}
     
      ' Get only short words
      Dim shortWords = From word In words _ Where word.Length <= 5 _ Select word
     
      ' Print each word out.
	  
      For Each word In shortWords
         Console.WriteLine(word)
      Next
	  
      Console.ReadLine()
   End Sub
End Module	

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

hello 
LINQ 
world

LINQ 的语法

LINQ 有两种语法。这些是以下内容。

Lamda(方法)语法

var longWords = words.Where( w ⇒ w.length > 10);
Dim longWords = words.Where(Function(w) w.length > 10)

查询(理解)语法

var longwords = from w in words where w.length > 10;
Dim longwords = from w in words where w.length > 10

LINQ 的类型

下面简要介绍了 LINQ 的类型。

  • LINQ 到对象
  • LINQ 转 XML(XLINQ)
  • LINQ 到数据集
  • LINQ 到 SQL (DLINQ)
  • LINQ 到实体

除了上述之外,还有一个名为 PLINQ 的 LINQ 类型,它是微软的并行 LINQ。

.NET 中的 LINQ 架构

LINQ 具有 3 层体系结构,其中最上层由语言扩展组成,底层由数据源组成,这些数据源通常是实现 IEnumerable <T> 或 IQueryable <T> 通用接口的对象。架构如下所示。

LINQ 架构

查询表达式

查询表达式只不过是一个 LINQ 查询,以类似于 SQL 的形式表达,带有 Select、Where 和 OrderBy 等查询运算符。查询表达式通常以关键字“From”开头。

要访问标准的 LINQ 查询运算符,默认情况下应导入命名空间 System.Query。这些表达式是用 C# 3.0 的声明式查询语法编写的。

下面的示例展示了一个完整的查询操作,它包括数据源创建、查询表达式定义和查询执行。

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Operators {
   class LINQQueryExpressions {
      static void Main() {
      
         // Specify the data source.
         int[] scores = new int[] { 97, 92, 81, 60 };

         // Define the query expression.
         IEnumerable<int> scoreQuery = from score in scores where score > 80 select score;

         // Execute the query.
		 
         foreach (int i in scoreQuery) {
            Console.Write(i + " ");
         }
		 
         Console.ReadLine();
      }
   }
}

当上面的代码被编译和执行时,它会产生以下结果 –

97 92 81

扩展方法

在 .NET 3.5 中引入的扩展方法仅在静态类中声明,并允许将自定义方法包含到对象中以执行一些精确的查询操作来扩展类,而不是该类的实际成员。这些也可以过载。

简而言之,扩展方法用于将查询表达式转换为传统的方法调用(面向对象)。

LINQ 和存储过程的区别

LINQ 和存储过程之间存在一系列差异。下面提到了这些差异。

  • 存储过程比 LINQ 查询快得多,因为它们遵循预期的执行计划。

  • 与存储过程相比,执行 LINQ 查询时避免运行时错误更容易,因为前者具有 Visual Studio 的智能感知支持以及编译时期间的完整类型检查。

  • LINQ 允许使用 .NET 调试器进行调试,这不是存储过程。

  • 与存储过程相比,LINQ 提供对多个数据库的支持,在存储过程中,必须为不同类型的数据库重新编写代码。

  • 与部署一组存储过程相比,基于 LINQ 的解决方案的部署简单易行。

需要 LINQ

在使用 LINQ 之前,必须学习 C#、SQL 和将两者结合在一起以形成完整应用程序的各种 API。因为,这些数据源和编程语言面临阻抗不匹配;感觉需要简短的编码。

下面是一个示例,说明在 LINQ 出现之前,开发人员在查询数据时使用了多少不同的技术。

SqlConnection sqlConnection = new SqlConnection(connectString);
SqlConnection.Open();

System.Data.SqlClient.SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlConnection;

sqlCommand.CommandText = "Select * from Customer";
return sqlCommand.ExecuteReader (CommandBehavior.CloseConnection)  

有趣的是,在特色代码行中,查询仅由最后两个定义。使用 LINQ,可以在更短的时间内以可读的颜色编码形式编写相同的数据查询,如下面提到的形式。

Northwind db = new Northwind(@"C:\Data\Northwnd.mdf");
var query = from c in db.Customers select c;

LINQ的优势

LINQ 提供了许多优点,其中最重要的是其强大的表达能力,使开发人员能够以声明方式进行表达。下面给出了 LINQ 的其他一些优点。

  • LINQ 提供了语法高亮,证明有助于在设计时找出错误。

  • LINQ 提供 IntelliSense,这意味着轻松编写更准确的查询。

  • 在 LINQ 中编写代码的速度相当快,因此开发时间也显着减少。

  • 由于 LINQ 集成在 C# 语言中,因此可以轻松调试。

  • 由于其分层功能,使用 LINQ 可以轻松查看两个表之间的关系,这使得在更短的时间内组合多个表的查询成为可能。

  • LINQ 允许在查询许多不同的数据源时使用单一的 LINQ 语法,这主要是因为它的统一基础。

  • LINQ 是可扩展的,这意味着可以使用 LINQ 的知识来查询新的数据源类型。

  • LINQ 提供了在单个查询中连接多个数据源以及将复杂问题分解为一组易于调试的短查询的功能。

  • LINQ 提供了将一种数据类型转换为另一种数据类型的简单转换,例如将 SQL 数据转换为 XML 数据。

LINQ – 环境设置

在开始使用 LINQ 程序之前,最好先了解设置 LINQ 环境的细微差别。LINQ 需要一个 .NET 框架,一个具有多种应用程序的革命性平台。LINQ 查询可以方便地用 C# 或 Visual Basic 编写。

Microsoft 通过 Visual Studio 为这两种语言(即 C# 和 Visual Basic)提供了工具。我们的例子都是用Visual Studio 2010编译和编写的。不过,也可以使用Visual Basic 2013版本。它是最新版本,与 Visual Studio 2012 有许多相似之处。

在 Windows 7 上安装 Visual Studio 2010

Visual Studio 可以从安装介质(如 DVD)安装。需要管理员凭据才能在您的系统上成功安装 Visual Basic 2010。在安装之前断开所有可移动 USB 与系统的连接至关重要,否则安装可能会失败。安装所必需的一些硬件要求如下。

硬件要求

  • 1.6 GHz 或更高
  • 1 GB 内存
  • 3 GB(可用硬盘空间)
  • 5400 RPM 硬盘驱动器
  • DirectX 9 兼容显卡
  • 光驱

安装步骤

步骤 1 – 首先,在插入带有 Visual Studio 2010 包的 DVD 后,单击出现在屏幕上的弹出框中的媒体安装或运行程序

第 2 步– 现在设置 Visual Studio 将出现在屏幕上。选择安装 Microsoft Visual Studio 2010

LINQ环境

步骤 3 – 一旦您单击,该过程将启动,并且屏幕上将出现一个设置窗口。完成加载需要一些时间的安装组件后,单击“下一步”按钮进入下一步。

LINQ环境

Step 4 – 这是安装的最后一步,将出现一个起始页面,只需选择“我已阅读并接受许可条款”,然后单击“下一步”按钮。

LINQ环境

步骤 5 – 现在从屏幕上显示的选项页面中选择要安装的功能。您可以选择完整自定义选项。如果您的磁盘空间少于磁盘空间要求中显示的所需空间,请选择自定义。

LINQ环境

步骤 6 – 当您选择自定义选项时,将出现以下窗口。选择要安装的功能并单击更新或转到第 7 步。但是,建议不要使用自定义选项,因为将来您可能需要选择没有的功能。

LINQ环境

步骤 7 – 很快将显示一个弹出窗口,安装将开始,这可能需要很长时间。请记住,这是用于安装所有组件。

LINQ环境

步骤 8 – 最后,您将能够在安装已成功完成的窗口中查看消息。单击完成

LINQ环境

在 Visual Studio 2010 中使用 LINQ 编写 C# 程序

  • 启动 Visual Studio 2010 Ultimate edition 并从菜单中选择 File,然后选择 New Project。

  • 屏幕上将出现一个新项目对话框。

  • 现在在已安装的模板下选择 Visual C# 作为类别,然后选择控制台应用程序模板,如下图所示。

LINQ环境

  • 在底部的名称框中为您的项目命名,然后按 OK。

  • 新项目将出现在屏幕上新对话框右侧的解决方案资源管理器中。

LINQ环境

  • 现在从解决方案资源管理器中选择 Program.cs,您可以在以“使用系统”开头的编辑器窗口中查看代码。

  • 在这里,您可以开始编写以下 C# 程序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
			
namespace HelloWorld {
   class Program {
      static void Main(string[] args) {
      
         Console.WriteLine("Hello World")
         Console.ReadKey();
      } 		
   }
}
  • 按 F5 键并运行您的项目。强烈建议在运行项目之前通过选择FileSave All来保存项目。

在 Visual Studio 2010 中使用 LINQ 编写 VB 程序

  • 启动 Visual Studio 2010 Ultimate edition 并从菜单中选择 File,然后选择 New Project。

  • 屏幕上将出现一个新项目对话框。

  • 现在选择 Visual Basic 作为已安装模板下的类别,然后选择控制台应用程序模板。

  • 在底部的名称框中为您的项目命名,然后按 OK。

  • 您将获得一个带有 Module1.vb 的屏幕。在此处开始使用 LINQ 编写 VB 代码。

Module Module1

   Sub Main()
      Console.WriteLine("Hello World")
      Console.ReadLine()
   End Sub
   
End Module   
  • 按 F5 键并运行您的项目。强烈建议在运行项目之前通过选择FileSave All来保存项目。

当 C# 或 VB 的上述代码被编译并运行时,它会产生以下结果 –

Hello World

LINQ – 查询运算符

形成查询模式的一组扩展方法称为 LINQ 标准查询运算符。作为 LINQ 查询表达式的构建块,这些运算符提供了一系列查询功能,如过滤、排序、投影、聚合等。

LINQ 标准查询运算符可根据其功能分为以下几种。

  • 过滤运算符
  • 加入运算符
  • 投影操作
  • 排序运算符
  • 分组运算符
  • 转化次数
  • 级联
  • 聚合
  • 量词操作
  • 分区操作
  • 代运营
  • 设置操作
  • 平等
  • 元素运算符

过滤运算符

过滤是一种限制结果集的操作,使其只包含满足特定条件的选定元素。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
where 基于谓词函数过滤值 在哪里 在哪里
OfType 根据值作为指定类型的能力过滤值 不适用 不适用

加入运算符

联接是指以难以直接跟踪关系的数据源为对象的操作。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Join 运算符根据匹配的键连接两个序列 加入……加入……上……等于…… 从 x In …, y In … 其中 xa = ya
GroupJoin 连接两个序列并对匹配的元素进行分组 join … in … on … 等于 … into … 组加入……进入……在……

投影操作

投影是一种将对象转换为仅具有特定属性的全新形式的操作。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Select 运算符根据变换函数投影值 选择 选择
SelectMany 运算符将基于变换函数的值序列投影并将它们展平为单个序列 使用多个 from 子句 使用多个 From 子句

排序运算符

排序操作允许基于单个或多个属性对序列的元素进行排序。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
OrderBy 运算符按升序对值进行排序 订购单 订购方式
OrderByDescending 运算符按降序对值进行排序 orderby … 降序 排序方式 … 降序
ThenBy 按升序执行二次排序 订购…,… 按……订购,……
ThenByDescending 按降序执行二次排序 orderby …, … 降序 按……排序,……降序
Reverse 执行集合中元素顺序的反转 不适用 不适用

分组运算符

操作员根据共同的共享属性将数据放入一些组中。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
GroupBy 以组的形式组织一系列项目并将它们作为 IGrouping<key, element> 类型的 IEnumerable 集合返回 group … by -or- group … by … into … 分组……由……进入……
ToLookup 执行分组操作,其中返回一系列密钥对 不适用 不适用

转化次数

运算符更改输入对象的类型并用于各种应用程序。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
AsEnumerable 返回输入的类型为 IEnumerable<T> 不适用 不适用
AsQueryable A (generic) IEnumerable 转换为 (generic) IQueryable 不适用 不适用
Cast 将集合的元素强制转换为指定类型 使用显式类型的范围变量。例如:from string str in words 从……作为……
OfType 根据它们的值过滤值,这取决于它们被转换为特定类型的能力 不适用 不适用
ToArray 强制执行查询并将集合转换为数组 不适用 不适用
ToDictionary 基于键选择器函数将元素设置为 Dictionary<TKey, TValue> 并强制执行 LINQ 查询 不适用 不适用
ToList 通过将集合转换为 List<T> 强制执行查询 不适用 不适用
ToLookup 根据键选择器函数强制执行查询并将元素放入 Lookup<TKey, TElement> 不适用 不适用

级联

执行两个序列的连接,在操作方面与 Union 运算符非常相似,除了这不会删除重复项。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Concat 两个序列连接起来形成一个单一的序列。 不适用 不适用

聚合

执行任何类型的所需聚合并允许在 LINQ 中创建自定义聚合。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Aggregate 对集合的值进行操作以执行自定义聚合操作 不适用 不适用
Average 计算一组值的平均值 不适用 聚合……进入……进入平均值()
Count 计算集合中满足谓词函数的元素 不适用 聚合……进入……进入计数()
LonCount 计算巨大集合中满足谓词函数的元素 不适用 聚合……进入……进入 LongCount()
Max 找出集合中的最大值 不适用 聚合……进入……进入Max()
Min 找出集合中存在的最小值 不适用 聚合……进入……进入Min()
Sum 找出集合中值的总和 不适用 聚合…进入…进入Sum()

量词操作

当序列中的部分或全部元素满足特定条件时,这些运算符返回一个布尔值,即 True 或 False。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
All 如果序列的所有元素都满足谓词条件,则返回值“True” 不适用 聚合……在……到所有(……)
Any 通过搜索序列确定相同的元素是否满足指定条件 不适用 聚合……进入……进入任何()
Contains 如果发现序列中存在特定元素,则返回“真”值,如果序列不包含该特定元素,则返回“假”值 不适用 不适用

分区运算符

将输入序列分成两个单独的部分,而不重新排列序列的元素,然后返回其中之一。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Skip 跳过序列中某些指定数量的元素并返回剩余的元素 不适用 跳过
SkipWhile 与 Skip 相同,唯一的例外是要跳过的元素数量由布尔条件指定 不适用 跳过时间
Take 从序列中取出指定数量的元素并跳过其余元素 不适用
TakeWhile 与 Take 相同,除了要采用的元素数量由布尔条件指定 不适用 花点时间

代运营

代运算符创建了一个新的值序列。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
DefaultIfEmpty 应用于空序列时,在序列内生成默认元素 不适用 不适用
Empty 返回一个空的值序列,是最简单的分代运算符 不适用 不适用
Range 生成具有整数或数字序列的集合 不适用 不适用
Repeat 生成包含特定长度的重复值的序列 不适用 不适用

设置操作

集合操作有四个运算符,每个运算符根据不同的标准产生一个结果。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
Distinct 通过过滤重复数据(如果有)从集合中生成唯一值列表 不适用 清楚的
Except 比较两个集合的值并返回一个集合中不在另一个集合中的值 不适用 不适用
Intersect 返回在两个单独的集合中发现相同的值集 不适用 不适用
Union 将两个不同集合的内容合并到一个列表中,该列表也没有任何重复的内容 不适用 不适用

平等

比较两个句子(可枚举)并确定它们是否完全匹配。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
SequenceEqual 如果发现两个序列彼此相同,则结果为布尔值 不适用 不适用

元素运算符

除了 DefaultIfEmpty,其余 8 个标准查询元素运算符都返回集合中的单个元素。

显示示例

Operator 描述 C# 查询表达式语法 VB 查询表达式语法
ElementAt 返回集合中特定索引中存在的元素 不适用 不适用
ElementAtOrDefault 与 ElementAt 相同,不同之处在于它还返回默认值以防特定索引超出范围 不适用 不适用
First 检索集合中的第一个元素或满足特定条件的第一个元素 不适用 不适用
FirstOrDefault 与 First 相同,除了在不存在此类元素的情况下它还返回默认值 不适用 不适用
Last 检索集合中存在的最后一个元素或满足特定条件的最后一个元素 不适用 不适用
LastOrDefault 与 Last 相同,除了在不存在任何此类元素的情况下它还返回默认值的事实 不适用 不适用
Single 返回集合的单独元素或满足特定条件的单独元素 不适用 不适用
SingleOrDefault 与 Single 相同,但如果不存在任何此类单独元素,则它还返回默认值 不适用 不适用
DefaultIfEmpty 如果集合或列表为空或 null,则返回默认值 不适用 不适用

LINQ – SQL

LINQ to SQL 为将关系数据作为对象进行管理提供了基础结构(运行时)。它是 .NET Framework 3.5 版的一个组件,能够将对象模型的语言集成查询转换为 SQL。然后将这些查询发送到数据库以供执行。从数据库中获取结果后,LINQ to SQL 再次将它们转换为对象。

LINQ To SQL 介绍

对于大多数 ASP.NET 开发人员来说,LINQ to SQL(也称为 DLINQ)是语言集成查询的一个激动人心的部分,因为它允许使用常用的 LINQ 表达式查询 SQL 服务器数据库中的数据。它还允许更新、删除和插入数据,但它遭受的唯一缺点是它对 SQL 服务器数据库的限制。但是,与 ADO.NET 相比,LINQ to SQL 有许多优点,例如降低复杂性、代码行数少等等。

下图显示了 LINQ to SQL 的执行架构。

LINQ SQL 架构

如何使用 LINQ to SQL?

步骤 1 – 与数据库服务器建立新的“数据连接”。查看 &arrar 服务器资源管理器 &arrar 数据连接 &arrar 添加连接

LINQ 到 SQL

步骤 2 – 添加 LINQ To SQL 类文件

LINQ 到 SQL

步骤 3 – 从数据库中选择表并将其拖放到新的 LINQ to SQL 类文件中。

LINQ 到 SQL

步骤 4 – 将表添加到类文件。

LINQ 到 SQL

使用 LINQ to SQL 查询

使用 LINQ to SQL 执行查询的规则与标准 LINQ 查询的规则类似,即查询执行延迟或立即执行。有各种组件在使用 LINQ to SQL 执行查询时发挥作用,以下是这些组件。

  • LINQ to SQL API – 代表应用程序请求执行查询并将其发送到 LINQ to SQL Provider。

  • LINQ to SQL Provider – 将查询转换为 Transact SQL(T-SQL) 并将新查询发送到 ADO Provider 以执行。

  • ADO Provider – 执行查询后,将结果以 DataReader 的形式发送到 LINQ to SQL Provider,后者又将其转换为用户对象的形式。

应该注意的是,在执行 LINQ to SQL 查询之前,通过 DataContext 类连接到数据源至关重要。

使用 LINQ To SQL 插入、更新和删除

添加或插入

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);           

         //Create new Employee
		 
         Employee newEmployee = new Employee();
         newEmployee.Name = "Michael";
         newEmployee.Email = "yourname@companyname.com";
         newEmployee.ContactNo = "343434343";
         newEmployee.DepartmentId = 3;
         newEmployee.Address = "Michael - USA";

         //Add new Employee to database
         db.Employees.InsertOnSubmit(newEmployee);

         //Save changes to Database.
         db.SubmitChanges();

         //Get new Inserted Employee            
         Employee insertedEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("Michael"));

         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, Address = {4}",
                          insertedEmployee.EmployeeId, insertedEmployee.Name, insertedEmployee.Email, 
                          insertedEmployee.ContactNo, insertedEmployee.Address);

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim newEmployee As New Employee()
	  
      newEmployee.Name = "Michael"
      newEmployee.Email = "yourname@companyname.com"
      newEmployee.ContactNo = "343434343"
      newEmployee.DepartmentId = 3
      newEmployee.Address = "Michael - USA"
     
      db.Employees.InsertOnSubmit(newEmployee)
     
      db.SubmitChanges()
     
      Dim insertedEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("Michael"))

      Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, 
         Address = {4}", insertedEmployee.EmployeeId, insertedEmployee.Name,
         insertedEmployee.Email, insertedEmployee.ContactNo, insertedEmployee.Address)

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	 
   End Sub
  
End Module

编译并运行上述 C# 或 VB 代码时,会产生以下结果 –

Emplyee ID = 4, Name = Michael, Email = yourname@companyname.com, ContactNo = 
343434343, Address = Michael - USA

Press any key to continue.

更新

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);

         //Get Employee for update
         Employee employee = db.Employees.FirstOrDefault(e =>e.Name.Equals("Michael"));

         employee.Name = "George Michael";
         employee.Email = "yourname@companyname.com";
         employee.ContactNo = "99999999";
         employee.DepartmentId = 2;
         employee.Address = "Michael George - UK";

         //Save changes to Database.
         db.SubmitChanges();

         //Get Updated Employee            
         Employee updatedEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("George Michael"));

         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, Address = {4}",
                          updatedEmployee.EmployeeId, updatedEmployee.Name, updatedEmployee.Email, 
                          updatedEmployee.ContactNo, updatedEmployee.Address);

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
  
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim employee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("Michael"))

      employee.Name = "George Michael"
      employee.Email = "yourname@companyname.com"
      employee.ContactNo = "99999999"
      employee.DepartmentId = 2
      employee.Address = "Michael George - UK"

      db.SubmitChanges()
          
      Dim updatedEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("George Michael"))

      Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3},
         Address = {4}", updatedEmployee.EmployeeId, updatedEmployee.Name, 
         updatedEmployee.Email, updatedEmployee.ContactNo, updatedEmployee.Address)

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

编译并运行上述 C# 或 Vb 代码时,会产生以下结果 –

Emplyee ID = 4, Name = George Michael, Email = yourname@companyname.com, ContactNo = 
999999999, Address = Michael George - UK

Press any key to continue.

删除

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = newLinqToSQLDataContext(connectString);

         //Get Employee to Delete
         Employee deleteEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("George Michael"));

         //Delete Employee
         db.Employees.DeleteOnSubmit(deleteEmployee);

         //Save changes to Database.
         db.SubmitChanges();

         //Get All Employee from Database
         var employeeList = db.Employees;
         foreach (Employee employee in employeeList) {
            Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}",
               employee.EmployeeId, employee.Name, employee.Email, employee.ContactNo);
         }            

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim deleteEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("George Michael"))

      db.Employees.DeleteOnSubmit(deleteEmployee)

      db.SubmitChanges()

      Dim employeeList = db.Employees
	  
      For Each employee As Employee In employeeList
         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}",
            employee.EmployeeId, employee.Name, employee.Email, employee.ContactNo)
      Next 

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub
   
End Module

编译并运行上述 C# 或 VB 代码时,会产生以下结果 –

Emplyee ID = 1, Name = William, Email = abc@gy.co, ContactNo = 999999999
Emplyee ID = 2, Name = Miley, Email = amp@esds.sds, ContactNo = 999999999
Emplyee ID = 3, Name = Benjamin, Email = asdsad@asdsa.dsd, ContactNo = 

Press any key to continue.

LINQ – 对象

LINQ to Objects 提供了使用任何支持 IEnumerable<T> 的 LINQ 查询来访问内存中的数据集合,而无需像 LINQ to SQL 或 LINQ to XML 那样需要 LINQ 提供程序 (API)。

LINQ to Objects 介绍

LINQ to Objects 中的查询通常仅返回 IEnumerable<T> 类型的变量。简而言之,LINQ to Objects 如前所述提供了一种全新的集合方法,编写长代码(非常复杂的 foreach 循环)以从集合中检索数据至关重要,现在已被编写清晰描述所需数据的声明性代码所取代这是检索所需的。

与传统的 foreach 循环相比,LINQ to Objects 还具有许多优点,例如更具可读性、强大的过滤、分组功能、以最少的应用程序编码增强排序。此类 LINQ 查询本质上也更紧凑,无需任何修改或只需稍加修改即可移植到任何其他数据源。

下面是一个简单的 LINQ to Objects 示例 –

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LINQtoObjects {
   class Program {
      static void Main(string[] args) {
      
         string[] tools = { "Tablesaw", "Bandsaw", "Planer", "Jointer", "Drill", "Sander" };
         var list = from t in tools select t;

         StringBuilder sb = new StringBuilder();

         foreach (string s in list) {
            sb.Append(s + Environment.NewLine);
         }
		 
         Console.WriteLine(sb.ToString(), "Tools");
         Console.ReadLine();
      }
   }
}

在示例中,字符串数组(工具)用作要使用 LINQ to Objects 查询的对象集合。

Objects query is:
var list = from t in tools select t;

当上面的代码被编译和执行时,它会产生以下结果 –

Tablesaw
Bandsaw
Planer
Jointer
Drill
Sander

使用 LINQ to Objects 在内存集合中查询

C#

using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQtoObjects {
   class Department {
      public int DepartmentId { get; set; }
      public string Name { get; set; }
   }

   class LinqToObjects {
      static void Main(string[] args) {
      
         List<Department> departments = new List<Department>();
			
         departments.Add(new Department { DepartmentId = 1, Name = "Account" });
         departments.Add(new Department { DepartmentId = 2, Name = "Sales" });
         departments.Add(new Department { DepartmentId = 3, Name = "Marketing" });

         var departmentList = from d in departments
                              select d;

         foreach (var dept in departmentList) {
            Console.WriteLine("Department Id = {0} , Department Name = {1}",
               dept.DepartmentId, dept.Name);
         }
		 
         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq

Module Module1

   Sub Main(ByVal args As String())

      Dim account As New Department With {.Name = "Account", .DepartmentId = 1}
      Dim sales As New Department With {.Name = "Sales", .DepartmentId = 2}
      Dim marketing As New Department With {.Name = "Marketing", .DepartmentId = 3}

      Dim departments As New System.Collections.Generic.List(Of Department)(New Department() {account, sales, marketing})

      Dim departmentList = From d In departments

      For Each dept In departmentList
         Console.WriteLine("Department Id = {0} , Department Name = {1}", dept.DepartmentId, dept.Name)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub

   Class Department
      Public Property Name As String
      Public Property DepartmentId As Integer
   End Class
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Department Id = 1, Department Name = Account
Department Id = 2, Department Name = Sales
Department Id = 3, Department Name = Marketing

Press any key to continue.

LINQ – 数据集

数据集在内存中提供了非常有用的数据表示,并用于各种基于数据的应用程序。LINQ to Dataset 作为 LINQ to ADO.NET 的一项技术,有助于以轻松的方式对 Dataset 的数据执行查询并提高生产力。

LINQ To Dataset 介绍

LINQ to Dataset 使开发人员的查询任务变得简单。他们不需要用特定的查询语言编写查询,而是可以用编程语言编写。LINQ to Dataset 还可用于查询从多个数据源合并数据的位置。这也不需要任何 LINQ 提供程序,就像用于访问内存集合中的数据的 LINQ to SQL 和 LINQ to XML 一样。

下面是一个简单的 LINQ to Dataset 查询示例,其中首先获取数据源,然后用两个数据表填充数据集。在两个表之间建立关系,并通过 join 子句针对两个表创建 LINQ 查询。最后,foreach 循环用于显示所需的结果。

C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LINQtoDataset {
   class Program {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         string sqlSelect = "SELECT * FROM Department;" + "SELECT * FROM Employee;";

         // Create the data adapter to retrieve data from the database
         SqlDataAdapter da = new SqlDataAdapter(sqlSelect, connectString);
        
         // Create table mappings
         da.TableMappings.Add("Table", "Department");
         da.TableMappings.Add("Table1", "Employee");

         // Create and fill the DataSet
         DataSet ds = new DataSet();
         da.Fill(ds);

         DataRelation dr = ds.Relations.Add("FK_Employee_Department",
                           ds.Tables["Department"].Columns["DepartmentId"],
                           ds.Tables["Employee"].Columns["DepartmentId"]);

         DataTable department = ds.Tables["Department"];
         DataTable employee = ds.Tables["Employee"];

         var query = from d in department.AsEnumerable()
                     join e in employee.AsEnumerable()
                     on d.Field<int>("DepartmentId") equals
                     e.Field<int>("DepartmentId")                        
                     select new {
                        EmployeeId = e.Field<int>("EmployeeId"),
                        Name = e.Field<string>("Name"),                            
                        DepartmentId = d.Field<int>("DepartmentId"),                            
                        DepartmentName = d.Field<string>("Name")
                     };

         foreach (var q in query) {
            Console.WriteLine("Employee Id = {0} , Name = {1} , Department Name = {2}",
               q.EmployeeId, q.Name, q.DepartmentName);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Data.SqlClient
Imports System.Linq

Module LinqToDataSet

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim sqlSelect As String = "SELECT * FROM Department;" + "SELECT * FROM Employee;"
      Dim sqlCnn As SqlConnection = New SqlConnection(connectString)
      sqlCnn.Open()

      Dim da As New SqlDataAdapter
      da.SelectCommand = New SqlCommand(sqlSelect, sqlCnn)

      da.TableMappings.Add("Table", "Department")
      da.TableMappings.Add("Table1", "Employee")

      Dim ds As New DataSet()
      da.Fill(ds)

      Dim dr As DataRelation = ds.Relations.Add("FK_Employee_Department", ds.Tables("Department").Columns("DepartmentId"), ds.Tables("Employee").Columns("DepartmentId"))

      Dim department As DataTable = ds.Tables("Department")
      Dim employee As DataTable = ds.Tables("Employee")

      Dim query = From d In department.AsEnumerable()
                  Join e In employee.AsEnumerable() On d.Field(Of Integer)("DepartmentId") Equals
                  e.Field(Of Integer)("DepartmentId")
                  Select New Person With { _
                        .EmployeeId = e.Field(Of Integer)("EmployeeId"),
                        .EmployeeName = e.Field(Of String)("Name"),
                        .DepartmentId = d.Field(Of Integer)("DepartmentId"),
                        .DepartmentName = d.Field(Of String)("Name")
                  }

      For Each e In query
         Console.WriteLine("Employee Id = {0} , Name = {1} , Department Name = {2}", e.EmployeeId, e.EmployeeName, e.DepartmentName)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
  
   Class Person
      Public Property EmployeeId As Integer
      Public Property EmployeeName As String
      Public Property DepartmentId As Integer
      Public Property DepartmentName As String
   End Class
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Employee Id = 1, Name = William, Department Name = Account
Employee Id = 2, Name = Benjamin, Department Name = Account
Employee Id = 3, Name = Miley, Department Name = Sales

Press any key to continue.

使用 LinQ to Dataset 查询数据集

在开始使用 LINQ to Dataset 查询数据集之前,将数据加载到数据集至关重要,这是通过使用 DataAdapter 类或通过 LINQ to SQL 来完成的。使用 LINQ to Dataset 制定查询与使用 LINQ 和其他启用 LINQ 的数据源制定查询非常相似。

单表查询

在以下单表查询中,从 SalesOrderHeaderTtable 中收集所有在线订单,然后将订单 ID、订单日期以及订单编号显示为输出。

C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinqToDataset {
   class SingleTable {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         string sqlSelect = "SELECT * FROM Department;";

         // Create the data adapter to retrieve data from the database
         SqlDataAdapter da = new SqlDataAdapter(sqlSelect, connectString);

         // Create table mappings
         da.TableMappings.Add("Table", "Department");           

         // Create and fill the DataSet
         DataSet ds = new DataSet();
         da.Fill(ds);

         DataTable department = ds.Tables["Department"];            

         var query = from d in department.AsEnumerable()                        
         select new {
            DepartmentId = d.Field<int>("DepartmentId"),
            DepartmentName = d.Field<string>("Name")
         };

         foreach (var q in query) {
            Console.WriteLine("Department Id = {0} , Name = {1}",
               q.DepartmentId, q.DepartmentName);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Data.SqlClient
Imports System.Linq

Module LinqToDataSet

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim sqlSelect As String = "SELECT * FROM Department;"
      Dim sqlCnn As SqlConnection = New SqlConnection(connectString)
      sqlCnn.Open()

      Dim da As New SqlDataAdapter
      da.SelectCommand = New SqlCommand(sqlSelect, sqlCnn)

      da.TableMappings.Add("Table", "Department")
      Dim ds As New DataSet()
      da.Fill(ds)

      Dim department As DataTable = ds.Tables("Department")

      Dim query = From d In department.AsEnumerable()
      Select New DepartmentDetail With {
         .DepartmentId = d.Field(Of Integer)("DepartmentId"),
            .DepartmentName = d.Field(Of String)("Name")
      }

      For Each e In query
         Console.WriteLine("Department Id = {0} , Name = {1}", e.DepartmentId, e.DepartmentName)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub

   Public Class DepartmentDetail
      Public Property DepartmentId As Integer
      Public Property DepartmentName As String
   End Class
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Department Id = 1, Name = Account
Department Id = 2, Name = Sales
Department Id = 3, Name = Pre-Sales
Department Id = 4, Name = Marketing

Press any key to continue.

LINQ – XML

LINQ to XML 提供了对所有 LINQ 功能(如标准查询运算符、编程接口等)的轻松访问。集成在 .NET 框架中,LINQ to XML 还充分利用了 .NET 框架功能,如调试、编译时检查、强类型还有很多话要说。

LINQ to XML 介绍

使用 LINQ to XML 时,将 XML 文档加载到内存中很容易,查询和文档修改也更容易。还可以将内存中存在的 XML 文档保存到磁盘并对其进行序列化。它消除了开发人员学习有点复杂的 XML 查询语言的需要。

LINQ to XML 在 System.Xml.Linq 命名空间中具有强大的功能。这具有使用 XML 所需的所有 19 个类。这些类是以下类。

  • 属性
  • XC数据
  • 评论
  • 容器
  • X声明
  • X文档
  • 文档类型
  • 元素
  • 名称
  • 命名空间
  • 节点
  • XNodeDocumentOrderComparer
  • XNodeEqualityComparer
  • 对象
  • XObjectChange
  • XObjectChangeEventArgs
  • XObjectEventHandler
  • XProcessing指令
  • 文本

使用 LINQ 读取 XML 文件

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(ByVal args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
                           "<Department>Account</Department>" & vbCr & vbLf & 
                           "<Department>Sales</Department>" & vbCr & vbLf & 
                           "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
                           "<Department>Marketing</Department>" & vbCr & vbLf & 
                           "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Department Name - Account
Department Name - Sales
Department Name - Pre-Sales
Department Name - Marketing

Press any key to continue. 

添加新节点

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         //Add new Element
         xdoc.Element("Departments").Add(new XElement("Department", "Finance"));

         //Add new Element at First
         xdoc.Element("Departments").AddFirst(new XElement("Department", "Support"));

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(ByVal args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
     	                   "<Department>Account</Department>" & vbCr & vbLf & 
     	                   "<Department>Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Marketing</Department>" & vbCr & vbLf & 
     	                   "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)

      xdoc.Element("Departments").Add(New XElement("Department", "Finance"))
     
      xdoc.Element("Departments").AddFirst(New XElement("Department", "Support"))

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Department Name - Support
Department Name - Account
Department Name - Sales
Department Name - Pre-Sales
Department Name - Marketing
Department Name - Finance

Press any key to continue.

删除特定节点

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Support</Department>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       <Department>Finance</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         //Remove Sales Department
         xdoc.Descendants().Where(s =>s.Value == "Sales").Remove(); 

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
     	                   "<Department>Support</Department>" & vbCr & vbLf & 
     	                   "<Department>Account</Department>" & vbCr & vbLf & 
     	                   "<Department>Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Marketing</Department>" & vbCr & vbLf & 
     	                   "<Department>Finance</Department>" & vbCr & vbLf & 
                           "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)
     
      xdoc.Descendants().Where(Function(s) s.Value = "Sales").Remove()

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

Department Name - Support
Department Name - Account
Department Name - Pre-Sales
Department Name - Marketing
Department Name - Finance

Press any key to continue. 

LINQ – 实体

作为 ADO.NET 实体框架的一部分,LINQ to Entities 比 LINQ to SQL 更灵活,但由于其复杂性和缺乏关键功能而不太流行。但是,它没有 LINQ to SQL 的限制,它只允许在 SQL 服务器数据库中查询数据,因为 LINQ to Entities 方便了在 Oracle、MySQL 等大量数据提供程序中的数据查询。

此外,它得到了 ASP.Net 的主要支持,因为用户可以利用数据源控件通过 LINQ to Entities 执行查询,并促进结果的绑定,而无需任何额外的编码。

由于这些优势,LINQ to Entities 已成为当今在数据库上使用 LINQ 的标准机制。还可以使用 LINQ to Entities 更改查询的数据详细信息并轻松提交批量更新。LINQ to Entities 最有趣的事实是它具有与 SQL 相同的语法,甚至具有相同的标准查询运算符组,如 Join、Select、OrderBy 等。

LINQ to Entities 查询创建和执行过程

  • ObjectContext(实体连接)构建ObjectQuery实例

  • 使用新构造的实例在 C# 或 Visual Basic (VB) 中编写查询

  • 将 LINQ 的标准查询运算符以及 LINQ 表达式转换为命令树

  • 执行查询将遇到的任何异常直接传递给客户端

  • 将所有查询结果返回给客户端

ObjectContext是实现与实体数据模型交互的主要类,换句话说,它充当连接 LINQ 和数据库的桥梁。命令树在这里是与实体框架兼容的查询表示。

另一方面,实体框架实际上是开发人员通常缩写为 ORM 的对象关系映射器,它根据数据库表生成业务对象和实体,并促进各种基本操作,如创建、更新、删除和读取. 下图显示了实体框架及其组件。

LINQ - 实体

将 LINQ 与实体模型结合使用的 ADD、UPDATE 和 DELETE 示例

首先按照以下步骤添加实体模型。

步骤 1 – 右键单击​​项目并单击添加新项目将打开如下窗口。选择 ADO.NET Entity Data Model 并指定名称,然后单击 Add。

LINQ - 实体模型

步骤 2 – 选择从数据库生成。

LINQ - 实体模型

步骤 3 – 从下拉菜单中选择数据库连接。

LINQ - 实体模型

步骤 4 – 选择所有表格。

LINQ - 实体模型

现在编写以下代码。

using DataAccess;
using System;
using System.Linq;

namespace LINQTOSQLConsoleApp {
   public class LinqToEntityModel {
      static void Main(string[] args) {

         using (LinqToSQLDBEntities context = new LinqToSQLDBEntities()) {
            //Get the List of Departments from Database
            var departmentList = from d in context.Departments
            select d;

            foreach (var dept in departmentList) {
               Console.WriteLine("Department Id = {0} , Department Name = {1}",
                  dept.DepartmentId, dept.Name);
            }

            //Add new Department
            DataAccess.Department department = new DataAccess.Department();
            department.Name = "Support";

            context.Departments.Add(department);
            context.SaveChanges();

            Console.WriteLine("Department Name = Support is inserted in Database");

            //Update existing Department
            DataAccess.Department updateDepartment = context.Departments.FirstOrDefault(d ⇒d.DepartmentId == 1);
            updateDepartment.Name = "Account updated";
            context.SaveChanges();

            Console.WriteLine("Department Name = Account is updated in Database");

            //Delete existing Department
            DataAccess.Department deleteDepartment = context.Departments.FirstOrDefault(d ⇒d.DepartmentId == 3);
            context.Departments.Remove(deleteDepartment);
            context.SaveChanges();

            Console.WriteLine("Department Name = Pre-Sales is deleted in Database");

            //Get the Updated List of Departments from Database
            departmentList = from d in context.Departments
            select d;

            foreach (var dept in departmentList) {
               Console.WriteLine("Department Id = {0} , Department Name = {1}",
                  dept.DepartmentId, dept.Name);
            }
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

当上面的代码被编译和执行时,它会产生以下结果 –

LINQ - 实体模型结果

LINQ – Lambda 表达式

术语“Lambda 表达式”的名称源自“lambda”演算,而后者又是一种用于定义函数的数学符号。Lambda 表达式作为 LINQ 方程的可执行部分在运行时以某种方式转换逻辑,因此它可以方便地传递到数据源。但是,lambda 表达式不仅限于在 LINQ 中找到应用程序。

这些表达式由以下语法表示 –

(Input parameters) ⇒ Expression or statement block

这是一个 lambda 表达式的例子 –

y ⇒ y * y

上面的表达式指定了一个名为 y 的参数,并且 y 的值是平方的。但是,无法以这种形式执行 lambda 表达式。C# 中的 lambda 表达式示例如下所示。

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {

      delegate int del(int i);
      static void Main(string[] args) {

         del myDelegate = y ⇒ y * y;
         int j = myDelegate(5);
         Console.WriteLine(j);
         Console.ReadLine();
      }
   }
}

VB

Module Module1
   Private Delegate Function del(ByVal i As Integer) As Integer
   
   Sub Main(ByVal args As String())
   
      Dim myDelegate As del = Function(y) y * y
      Dim j As Integer = myDelegate(5)
      Console.WriteLine(j)
      Console.ReadLine()
	  
   End Sub
   
End Module

编译并执行上述 C# 或 VB 代码时,会产生以下结果 –

25

表达式 Lambda

由于上面显示的 lambda 表达式语法中的表达式位于右侧,因此它们也称为表达式 lambda。

异步 Lambda

通过使用 async 关键字合并异步处理而创建的 lambda 表达式称为 async lambdas。以下是异步 lambda 的示例。

Func<Task<string>> getWordAsync = async()⇒ “hello”;

标准查询运算符中的 Lambda

查询运算符中的 lambda 表达式根据需要由相同的表达式求值,并持续作用于输入序列中的每个元素而不是整个序列。Lambda 表达式允许开发人员将他们自己的逻辑输入到标准查询运算符中。在下面的示例中,开发人员使用 ‘Where’ 运算符通过使用 lambda 表达式从给定列表中回收奇数值。

C#

//Get the average of the odd Fibonacci numbers in the series... 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {     
      static void Main(string[] args) {
      
         int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
         double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
         Console.WriteLine(averageValue);
         Console.ReadLine();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
      Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
	  
      Console.WriteLine(averageValue)
      Console.ReadLine()
	  
   End Sub
   
End Module

当上面的代码被编译和执行时,它会产生以下结果 –

7.33333333333333

Lambda 中的类型推断

在 C# 中,类型推断可以在各种情况下方便地使用,而且无需明确指定类型。但是,在 lambda 表达式的情况下,类型推断仅在每个类型都已指定为编译器必须满足时才有效。让我们考虑以下示例。

delegate int Transformer (int i);

这里编译器使用类型推断来利用 x 是整数这一事实,这是通过检查 Transformer 的参数类型来完成的。

Lambda 表达式中的变量范围

在 lambda 表达式中使用变量范围时有一些规则,例如在 lambda 表达式中启动的变量并不意味着在外部方法中可见。还有一条规则是,除非引用该变量的委托有资格进行垃圾收集,否则不会对捕获的变量进行垃圾收集。此外,有一条规则禁止 lambda 表达式中的 return 语句导致封闭方法的返回。

这是一个演示 lambda 表达式中变量作用域的示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {
      delegate bool D();
      delegate bool D2(int i);

      class Test {
         D del;
         D2 del2;
			
         public void TestMethod(int input) {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () ⇒ { j = 10; return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) ⇒ { return x == j; };

            // Demonstrate value of j:            
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);        // Invoke the delegate.
            bool boolResult = del();
           
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
         }

         static void Main() {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);
           
            Console.WriteLine(result);

            Console.ReadKey();
         }
      }
   }
}

当上面的代码被编译和执行时,它会产生以下结果 –

j = 0
j = 10. b = True
True

表达式树

Lambda 表达式广泛用于表达式树的构建。表达式树在类似于树的数据结构中提供代码,其中每个节点本身都是一个表达式,如方法调用,也可以是二元运算,如 x<y。下面是使用 lambda 表达式构建表达式树的示例。

语句 Lambda

还有由两个或三个语句组成的语句 lambda,但不用于构建表达式树。return 语句必须写在语句 lambda 中。

语句 lambda 的语法

(params)⇒ {statements}

语句 lambda 的示例

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace lambdaexample {
   class Program {
      static void Main(string[] args) {
         int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

         foreach (int i in source.Where(x ⇒ 
            {
               if (x <= 3)
                  return true;
               else if (x >= 7)
                  return true;
               return false;
            }
         ))
        Console.WriteLine(i);
        Console.ReadLine();
      }
   }
}

当上面的代码被编译和执行时,它会产生以下结果 –

3
8
1
7
9
2
8

Lambda表达式被用作基于方法的LINQ查询参数,决不允许有一个地方运营商的左侧就像作为就像匿名方法。尽管 Lambda 表达式与匿名方法非常相似,但它们完全不限于仅用作委托。

使用 lambda 表达式时要记住的要点

  • 一个 lambda 表达式可以返回一个值并且可以有参数。

  • 可以使用 lambda 表达式以多种方式定义参数。

  • 如果 lambda 表达式中有单个语句,则不需要大括号,而如果有多个语句,则必须编写大括号和返回值。

  • 使用 lambda 表达式,可以通过称为闭包的功能访问存在于 lambda 表达式块之外的变量。应谨慎使用封闭件以避免出现任何问题。

  • 不可能在任何 lambda 表达式中执行任何不安全的代码。

  • Lambda 表达式不应用于运算符的左侧。

LINQ – ASP.Net

作为一组 .NET 框架扩展,LINQ 是 ASP.NET 开发人员访问数据的首选机制。ASP.NET 3.5 有一个内置工具 LINQDataSource 控件,可以在 ASP.NET 中轻松使用 LINQ。ASP.NET 使用上述控件作为数据源。现实生活中的项目大多包含网站或 Windows 应用程序,因此为了更好地理解 LINQ 与 ASP.NET 的概念,让我们从创建一个利用 LINQ 功能的 ASP.NET 网站开始。

为此,必须在您的系统上安装 Visual Studio 和 .NET 框架。打开 Visual Studio 后,转到文件 → 新建 → 网站。将打开一个弹出窗口,如下图所示。

LINQ - ASP.Net

现在,在左侧的模板下,将有两种语言选项来创建网站。选择Visual C#并选择ASP.NET Empty Web Site

选择要在系统上保存新网站的文件夹。然后按确定,很快解决方案资源管理器就会出现在您的屏幕上,其中包含所有 Web 文件。在解决方案资源管理器中右键单击 Default.aspx 并选择在浏览器中查看以在浏览器中查看默认的 ASP.NET 网站。很快,您的新 ASP.NET 网站将在 Web 浏览器中打开,如下面的屏幕截图所示。

LINQ - ASP.Net

.aspx 实际上是 ASP.NET 网站中使用的主要文件扩展名。默认情况下,Visual Studio 会为基本网站(如主页关于我们)创建所有必要的页面,您可以在其中方便地放置您的内容。该网站的代码在此处自动生成,也可以查看。

LINQ数据源控件

这是可能的UPDATE,INSERTDELETE在ASP.NET网站与LinqDataSource控件的帮助下页的数据。绝对不需要指定 SQL 命令,因为 LINQDataSource 控件为此类操作使用动态创建的命令。

该控件使用户可以通过标记文本中的属性设置,方便地在 ASP.NET 网页中使用 LINQ。LINQDataSource 与SqlDataSourceObjectDataSource等控件非常相似,因为它可用于将页面上的其他 ASP.NET 控件绑定到数据源。因此,我们必须有一个数据库来解释 LINQDataSource 控件调用的各种函数。

在开始解释 ASP.NET 网页形式的控件用法之前,必须打开 Microsoft Visual Studio Toolbox 并将 LINQDataSource 控件拖放到 ASP.NET 网站的 .aspx 页面,如下图所示。

LINQ - ASP.Net

下一步是通过选择员工记录的所有列来配置 LINQDataSource。

LINQ - ASP.Net

现在向 .aspx 页面添加一个 GridView 控件并如下图所示进行配置。GridView 控件功能强大,可以灵活地处理数据。配置控件后不久,它将出现在浏览器中。

LINQ - ASP.Net

现在可以在屏幕上查看 .aspx 页面的编码是 –

<!DOCTYPE html>

<html>
   <head runat = "server">
      <title></title>
   </head>

   <body>
      <form id = "form1" runat = "server">
         <div>
            <asp:GridView ID = "GridView1" runat = "server" AutoGenerateColumns = "False"
			
               DataKeyNames = "ContactID" DataSourceID = "LINQDataSource1">
               <Columns>
			   
                  <asp:BoundField DataField = "ContactID" HeaderText = "ContactID"
                     InsertVisible = "False" ReadOnly="True" SortExpression = "ContactID" />
                  <asp:CheckBoxField DataField = "NameStyle" HeaderText = "NameStyle"
                     SortExpression = "NameStyle" />
                  <asp:BoundField DataField = "Title" HeaderText = "Title" SortExpression = "Title" />
                  <asp:BoundField DataField = "FirstName" HeaderText = "FirstName"
                     SortExpression="FirstName" />
                  <asp:BoundField DataField = "MiddleName" HeaderText = "MiddleName"
                     SortExpression = "MiddleName" />
                  <asp:BoundField DataField = "LastName" HeaderText = "LastName"
                     SortExpression = "LastName" />
                  <asp:BoundField DataField = "Suffix" HeaderText = "Suffix"
                     SortExpression = "Suffix" />
                  <asp:BoundField DataField = "EmailAddress" HeaderText = "EmailAddress"
                     SortExpression = "EmailAddress" />
               </Columns>

            </asp:GridView>

            <br />

         </div>

         <asp:LINQDataSource ID = "LINQDataSource1" runat = "server"

            ContextTypeName = "LINQWebApp1.AdventureWorksDataContext" EntityTypeName = ""
               TableName = "Contacts">

         </asp:LINQDataSource>
      </form>
   </body>
</html>

这里应该注意的是,将属性 ContextTypeName 设置为代表数据库的类的属性是至关重要的。例如,这里将其指定为 LINQWebApp1.AdventureWorksDataContext,因为此操作将在 LINQDataSource 和数据库之间建立所需的连接。

使用 LINQ 在 ASP.NET 页面中插入、更新和删除数据

严格完成上述所有步骤后,LINQDataSource 控件中选择LINQDataSource 任务并选择所有启用插入、启用更新和启用删除的三个框,如下面的屏幕截图所示。

LINQ - ASP.Net

很快,声明性标记将显示在您的屏幕上,如下所示。

<asp:LINQDataSource 
   ContextTypeName = "LINQWebApp1.AdventureWorksDataContext" 
   TableName = "Contacts" 
   EnableUpdate = "true" 
   EnableInsert = "true" 
   EnableDelete = "true" 
   ID = "LINQDataSource1" 
   runat = "server">
</asp:LINQDataSource>

现在,由于有多个行和列,最好在 .aspx 表单上添加另一个控件,命名为 Detail View 或 Grid View 控件下方的 Master 控件,以仅显示网格选定行的详细信息。从 Detail View 控件中选择 Detail View Tasks,然后选中如下所示的复选框。

LINQ - ASP.Net

现在,只需保存更改并按 Ctrl + F5 即可在浏览器中查看页面,现在可以在详细视图控件上删除、更新和插入任何记录。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁