学习 LINQ:LINQ to SQL 提供程序





5.00/5 (2投票s)
LINQ to SQL 提供程序简介。
引言
LINQ 是 Language-INtegrated Queries 的缩写,它基本上使查询成为 C# 和 VB.NET 等 .NET 语言的一等公民(即,使它们在 Visual Studio 2008 的 IntelliSense 中可用)。
我们可以将 LINQ 与任何数据源一起使用。我们可以用我们选择的编程语言表达高效的查询行为,可选地将数据查询结果转换/整形为我们想要的任何格式,然后轻松地操作结果。启用 LINQ 的语言可以提供完整的类型安全和查询表达式的编译时检查,开发工具可以在编写 LINQ 代码时提供完整的 IntelliSense、调试和丰富的重构支持。
Using the Code
为什么我们需要 LINQ?
当开发人员接触到 LINQ 时,会想到一些基本问题:
- 为什么我们需要 LINQ 这样的工具?
- 以前的工具为什么不方便?
- LINQ 的创建只是为了使同时使用编程语言、关系数据和 XML 更方便吗?
回答这些问题肯定能让我们看到 LINQ 项目的重要性并欣赏它。众所周知,绝大多数开发的应用程序都访问数据或与关系数据库通信。要编程此类应用程序,学习 C# 等语言是不够的。我们需要学习另一种语言,如 SQL,以及将其与 C# 结合形成应用程序的 API。
LINQ 项目解决了 **数据!= 对象** 的问题,涉及关系数据、XML 数据等所有领域。这些领域的数据完全不同,最初并非为完全兼容地协同工作而创建。此外,我们现在使用面向对象语言通过对象访问和操作这些领域的数据,而对象是另一个完全不同的领域。因此,我们看到不同的数据存储之间存在严重的匹配或不兼容问题,而现在它们正变得相互依赖。
为了证实我们上面讨论的内容,让我们考虑关系数据与对象世界不兼容的场景。
- 关系数据库和面向对象语言的数据类型行为不同。
- 出于性能原因,数据库使用范式化,这导致数据的组织方式特定于关系数据模型。对象的组织基于继承、组合和复杂引用图的概念。数据库没有继承等概念。因此,由于这两个世界的模型本身就不同,因此弥合它们之间的差距变得困难。
- 编程模型不同。在 SQL 中,我们为所需数据编写精确的查询。如果我们在 C# 中想要相同的结果,我们必须遍历集合并执行一些条件操作,然后收集结果。因此,编程模型也不同。
- 在面向对象语言中,我们看到对象将数据和行为作为单个实体包含在自身中。这与关系模型截然不同,在关系模型中,数据与代码完全分离。
问题的实际示例
让我们看一个实际的代码示例,看看这两个世界有多么不同
.NET 框架类库包含一个名为 ADO.NET 的 API,用于访问关系数据库并在内存中表示关系数据。此 API 包含 SqlConnection、SqlCommand、SqlDataAdapter、SqlDataReader 等类。这些类的问题在于它们强制开发人员显式地处理表、记录和列,而 C# 和 VB.NET 等现代语言使用面向对象范例。
LINQ 通过消除编写大量用于将面向对象模型映射到关系数据库或 XML 的管道代码的负担,帮助我们提高数据密集型编程的生产力。
考虑下面这段用 .NET 编写的连接数据库的代码片段
SqlConnection MyCon = new SqlConnection("Data Source = X; Initial Catalog =Y ; User ID = Z; Password=***");
SqlCommand MyComm = new SqlCommand();
MyComm.CommandText = @"Select Name,CustomerID FROM Customers WHERE City =@City";
MyComm.Parameters.AddWithValue("@City", "Mysore");
MyCon.Open();
MyReader = MyComm.ExecuteReader();
if (MyReader.HasRows)
{
string NameCustomer = MyReader.GetString(0);
//Additional code omitted//
}
else
{
MessageBox.Show("Sorry No Data");
}
关于上述代码,我们可以注意到以下几点:
- 为实现一个简单功能编写了几个步骤
- 编写的查询只是普通字符串,因此在编译时不会被验证为查询,而是作为字符串。即使查询语法不正确,它也会通过所有编译检查
- 参数定义松散。例如,此处定义的列类型可能与服务器上的不同。在编译时无法检查这一点。
- 如果使用 DBxxx 类进行与提供程序无关的代码,则在此模型中无法使用特定于提供程序的方言或代码。
在这里我们看到了现有模型的局限性。那么答案是什么?
在 LINQ 中寻找解决方案
LINQ 旨在将数据查询和操作语言的功能深度集成到编程语言中。LINQ 消除了对象、数据库和 XML 之间的障碍。它使我们能够使用相同的语言集成工具来处理它们。例如,现在我们可以在同一个查询中处理来自关系数据库的数据和来自 XML 的数据。LINQ 使这变得容易。
我们获得的一些出色好处是:
- 查询在编译时检查。我们不再需要等到运行时才能检测到查询中的错误。
- 编写 LINQ 查询时,我们可以获得 Visual Studio 的 IntelliSense,这使得编码更快。
让我们看看 LINQ 的一些设计目标。
目标 |
动机 |
集成对象、关系数据和 XML |
需要针对不同语言和数据源的统一查询语法,以及需要单一处理模型。 |
在 C# 和 VB 中拥有 SQL 和 XQuery 的强大功能 |
将查询功能直接集成到编程模型中 |
语言的可扩展性模型 |
使其他编程语言得以实现 |
类型安全 |
编译时检查以避免问题 |
调试器支持 |
- |
关于 LINQ 的两种观点?
LINQ 可以被认为是两个互补的部分:
- 一组用于处理数据的工具
- 一组编程语言扩展
LINQ 作为一套工具
LINQ 确实改变了应用程序和组件处理和操作数据的一些方面。LINQ 中提供了一组提供程序供开发人员使用。这些提供程序包括 LINQ to Objects、LINQ to XML、LINQ to DataSet、LINQ to SQL、LINQ to Entities 等。所有这些提供程序都建立在一个共同的基础之上,该基础由查询运算符、查询表达式和表达式树等构建块组成。这些构建块使 LINQ 工具具有可扩展性。可以创建 LINQ 的其他变体以提供对各种数据源的访问。可以将文件系统、ActiveDirectory、Windows 管理规范 (WMI)、Windows 事件日志或任何其他数据源或 API 等各种数据源插入到 LINQ 中。
LINQ 作为一组编程语言扩展
LINQ 提供程序绝不是独立的工具。它们可以直接用于任何 .NET 编程语言。LINQ 允许我们通过针对各种数据源编写查询来访问信息。我们都非常熟悉编写 SQL 查询。即使在当今的数据访问技术中,我们仍然坚持在编程语言中编写查询,但使用特定于源的语法。LINQ 提供了与 SQL 相同的表达能力,但使用的是我们选择的编程语言。这使我们能够编写更短、更简洁的代码。例如,关键字 from、where、orderby、select 等现在已成为 C# 的一部分。这告诉我们 C# 已扩展以支持语言集成查询。
让我们开始吧
让我们开始深入了解 LINQ to SQL 并从数据库中读取数据。
步骤 1:在数据库中创建一个表
我已在此示例中在名为 MyServer 的服务器上名为 MyDatabase 的数据库中创建了一个名为 Parcel 的表。我将用于登录 MSSQL Server 2005 (MyServer) 的用户凭据是:
用户 ID:Arpan_Patro
密码:infy@123
Parcel 表的简要描述如下。
列名 |
列 ID |
ParcelID(主键) |
Varchar(5) |
状态 |
Varchar(10) |
ArriveCode |
Int |
步骤 2:在 Visual Studio 2008 中打开一个新的控制台应用程序
步骤 3:包含必要的命名空间
既然我们想用 Visual Studio 做一些新的事情,我们需要添加一些新的命名空间。这些命名空间已经添加到 VS2008 版本中。
using System.Data.Linq.Mapping;
using System.Linq;
using System.Data.Linq;
注意:如果命名空间未通过 IntelliSense 出现,您可能需要手动添加 System.Data.Linq
命名空间,然后尝试通过 IntelliSense 获取命名空间。
一个显而易见的问题随之而来:“我为什么需要这些,或者我通过添加这些命名空间获得了什么?”
我们将在接下来的步骤中探讨原因。
步骤 4:创建类(使用属性 Table 和 Column)
在此步骤中,我们使用 C# 语言创建表示数据库中对象的对象。通过用属性装饰普通类,对象与关系数据链接。两个最重要的属性是 Table 和 Column。
Table 属性用于修饰类。它的一个属性是 Name;它用于指定类对象所链接的表的名称。如果 Name 属性缺失,则类的名称将用作表的名称。用 Table 属性修饰的类称为*实体类*,实体类的一个实例称为实体。只有实体存储在数据库中。
例如:在我的示例中,我有一个名为 Parcel 的表,因此在 *Program.cs* 文件中,我编写了以下代码:
[Table(Name = "Parcel")]
public class Parcel
{
………..
Column
属性用于修饰实体类的字段或属性,以将它们与表的列关联起来。Column
属性也有几个属性,其中之一是 Name 属性。与 Table 的 Name
属性类似,它用于指定实体类的字段或属性所匹配的表中的字段。如果未指定此属性,则实体类的字段或属性的名称将被假定为表中字段的名称。
在我的示例中,我有三个列,我将其指定如下:
[Table(Name = "Parcel")]
public class Parcel
{
[Column]
public string ParcelID;
[Column]
public string Status;
[Column]
public int ArriveCode;
}
重要的是要知道 Table 和 Column 属性存在于 System.Data.Linq.Mapping
命名空间中。
步骤 5:创建 DataContext
简单来说,DataContext
是一种将查询传递给关系数据库的方式。它负责将我们的 LINQ 查询翻译成适当的 SQL 查询,并与指定的数据库通信。它的行为类似于 ADO.NET 中的 Connection 对象。我们必须将连接字符串传递给 DataContext
类的构造函数。这使得在当前数据上下文(稍后解释)中执行的 LINQ 查询能够在给定连接字符串指定的数据库上执行。
创建表和列后,我们现在将创建 DataContext
,如下所示,提供您自己的凭据、服务器名称。
[Database(Name = "MyDatabase")]
public class MyDataBase : DataContext
{
public Table<parcel> Parcel;
public MyDataBase()
: base("Data Source = MyServer ; Initial Catalog = MyDatabase ; User ID = Arpan_Patro ; Password = infy@123")
{ }
}</parcel>
DataContext
类位于 System.Data.Linq
命名空间中。
您可以将 Database
属性应用于任何强类型 DataContext
声明。
Database
属性是可选的。如果使用它,则必须使用 Name 属性提供一个名称。
如果您不应用此属性且连接未指定名称,则假定数据库与 DataContext
类同名。
我们上面所做的不仅仅是创建一个数据上下文,我们还对数据库进行了建模,并将我们之前创建的表类指定为这里的表(注意这里使用了泛型)。
步骤 6:编写 LINQ 查询
成功完成步骤 1 到 5 后,我们现在将按照以下方式在主方法中编写 LINQ 查询:
static void Main(string[] args)
{
MyDatabase MyConnection = new MyDatabase();
//This is the LINQ Query for fetching all the records from the Parcel Table
var Result = from myLinQ in MyConnection.Parcel
select new{
myLinQ.ParcelID, myLinQ.Status, myLinQ.ArriveCode};
//Displaying the Query Output onto the Console
foreach (var NewRow in Result)
{
Console.WriteLine("{0,-25} {1,-10}”+ “{2}",
NewRow.ParcelID.ToString(),
NewRow.Status.ToString(),NewRow.ArriveCode.ToString());
}
上面使用的 Var
是 C# 3.0 中的匿名类型。它会自动推断赋值操作右侧的类型并充当该类型。
如果你注意到 LINQ 查询在结构上与 SQL 查询有很大的相似之处。数据库返回的结果总是作为 IEnumerable
返回,所以我们可以使用 foreach
循环来访问结果集。
步骤 6:现在只需构建并执行
这展示了使用如此强大的工具并在 C# 中使用来自各种来源的数据编写复杂逻辑是多么容易。可以编写类似的代码来访问 XML 文件、对象、实体等中的数据。
摘要
在本文档中我们已经了解了:
- LINQ 在提供统一编程模型方面的重要性。
- LINQ 的设计目标
- 如何使用 LINQ to SQL 提供程序
参考资料
- 关键词定义来自 www.msdn.com
- LINQ in Action - Fabrice Marguerie, Steve Eichert 和 Jim Wooley, Manning Publications。