LinqToSql库与SQLite数据库查询

LinqToSql库是一个强大的工具,它能够将LINQ表达式树转换为SQL语句,这些语句可以执行在多种关系数据库管理系统(RDMS)上,而不仅仅是微软的SQL Server。本文将介绍LinqToSql库的主要功能,并展示如何在SQLiteSQL Server和Microsoft Access数据库中使用它进行查询。

LinqToSql库的功能

LinqToSql库实现了以下功能和特性:

  • 全面支持SQLite、SQL Server 2000/2005、Microsoft Access、MySQL(测试中)
  • 透明地在一个表达式中查询多个数据库,例如Microsoft Access数据库和SQL Server数据库
  • 翻译字符串、日期时间和可空类型中的函数调用和属性访问器,这些在SQL中有等价物,例如firstName.Length、firstName.ToUpper()、orderDate.Year、shippedDate.HasValue等
  • 实现所有IQueryable方法,例如GroupBy、Any、All、First、Sum、Average等
  • 正确且全面地翻译二元和一元表达式,这些表达式在SQL中有有效的翻译
  • 参数化查询而不是在SQL转换中嵌入常量
  • 缓存之前翻译过的表达式树
  • 不使用MARS(Multiple Active Result Sets),这是SQL Server2005特有的功能
  • 正确翻译SelectMany调用,即使查询源涉及方法调用,也不使用SQL Server2005特有的关键字CROSS APPLY

SQLite简介

SQLite是一个软件库,它实现了一个自包含的、无服务器的、零配置的、事务性的SQL数据库引擎。SQLite是世界上部署最广泛的SQL数据库引擎。它被用于无数的桌面计算机应用程序以及消费电子设备,包括手机、PDA和MP3播放器。SQLite的源代码是公共领域的。

设置SQLite

在下载并安装了SQLite.NET(一个优秀的ADO.NET包装器)和SQLite数据库浏览器(提供SQLite的图形用户界面)之后,将准备好运行下载中的示例。示例中已经完成了以下工作:

  • Northwind数据库已被转换为SQLite数据库,并放置在项目的\bin目录中
  • 已定义SQLite的提供程序工厂和连接字符串属性

设置运算符

将介绍几个设置运算符的例子,包括ALL、ANY和UNION。

以下查询将提供所有已下订单且所有订单都已发货到客户所在城市的客户的列表。

from c in customers where ( from o in c.Orders select o ).All(o => o.ShipCity == c.City) select new { c.CustomerID, c.ContactName };

这将产生以下SQL语句:

SELECT t0.CustomerID, t0.ContactName FROM Customers AS t0 WHERE ( SELECT COUNT(*) FROM Orders AS t1 WHERE ((t1.CustomerID = t0.CustomerID) AND NOT ((t1.ShipCity = t0.City))) ) = 0

以下查询将提供所有未下订单的客户的列表。

from customer in customers where !customer.Orders.Any() select new { customer.CustomerID, customer.ContactName };

这将产生以下SQL语句:

SELECT t0.CustomerID, t0.ContactName FROM Customers AS t0 WHERE NOT ( ( SELECT COUNT(*) FROM Orders AS t1 WHERE (t1.CustomerID = t0.CustomerID) ) > 0 )

以下查询将提供居住在伦敦的客户和员工的列表。

from c in customers.Where(d => d.City == "London") select new { ContactName = c.ContactName } .Union( from e in employees.Where(f => f.City == "London") select new { ContactName = e.LastName } );

这将产生以下SQL语句:

SELECT t2.ContactName FROM Customers AS t2 WHERE (t2.City = @p0) UNION SELECT t2.LastName FROM Employees AS t2 WHERE (t2.City = @p1)

兴趣点

虽然RDMS通过SQL暴露的核心功能在不同数据库之间非常相似,但更高级的功能通常根据使用的产品以非常不同的方式访问。例如,以下查询...

from order in orders where order.OrderDate.Value.Year > DateTime.Parse("1/1/1997").Year && order.CustomerID.StartsWith("B") select new { order.CustomerID, order.OrderID, order.OrderDate };

对于SQL Server,翻译将是:

SELECT t0.CustomerID, t0.OrderID, t0.OrderDate FROM Orders AS t0 WHERE ((datePart(yyyy, t0.OrderDate) > @p1) AND t0.CustomerID Like (@p0 + '%'))

但在SQLite中,翻译将是:

SELECT t0.CustomerID, t0.OrderID, t0.OrderDate FROM Orders AS t0 WHERE ((round(strftime('%Y', t0.OrderDate)) > @p1) AND Like(@p0 || '%', t0.CustomerID))

LinqToSql库通过不同的数据库系统暴露出核心功能,并且可以通过扩展它来产生针对选择的RDMS的正确SQL语法。下一篇文章将介绍如何扩展LinqToSql以适应不同的数据库系统,以及如何将用户定义的标量函数映射到存储过程/临时SQL。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485