随笔 - 89, 评论 - 163, 引用 - 33

导航

关于

标签

每月存档

最新留言

广告

LINQ在VB中是如何对Dataset工作的

 [原文作者]Jonathan Aneja

[原文链接]How LINQ to Dataset works in VB

   LINQ的核心要求任何数据源能够被查询,这基本上意味着它必须实现IEnumerable接口(实际情况要更复杂一点,详细的说明请参见Visual Basic 9.0语言规范之11.21.2一节,<Visual Basic 9.0 Language Specification >)。现在,当使用LINQDataset进行工作时我们就有了一个问题:DataTable没有实现IEnumerable,那么我们该如何来对它进行查询?
   如我们昨天<yesterday>所见,Visual Studio 2008中包含有一个名为 System.Data.DataSetExtensions.dllassembly,它定义了一个叫做AsEnumberable()的扩展方法<extension method>。这里是这个方法看上去的样子:
    <Extension()> _
    Public Function AsEnumerable(source As DataTable) As EnumerableRowCollection(Of DataRow)
   基本上,该方法接收一个DataTable,然后返回实现了IEnumberable(Of T)某个东西,然后LINQ就可以用它来构造标准的查询操作符了。因此,你需要做的是 import System.Data(默认情况下项目模板就会把这个做好),然后你就可以通过调用AsEnumberable()来使用LINQ对一个Dataset进行查询了:
   Dim customers = TestDS.Tables("Customers")
 
   Dim franceCustomers = From cust In customers.AsEnumerable() _
                          Where cust!Country = "France" _
                          Select cust
 
   现在,关于LINQVB中的工作方式的有趣事情之一是:你其实并不真正需要为上面的代码去显式的调用AsEnumberable()以通过编译。即使DataTable没有实现IEnumerable,编译器会通过自动查找某些可以将之转换成某种可被查询的东西的方法来帮助你解决这个问题。当VB编译器碰到一个要对某个未实现IEnumberableIEnumerable(Of T)IQueryable、或IQueryable(Of T)的类型进行工作的LINQ查询时,它会依次执行以下工作:
1. 检查该类型上是否有一个标准的Select方法可用;
2. 检查该类型上是否有一个名为AsQueryable的实例方法,该方法应能返回一个可查询的类型;
3. 检查该类型上是否有一个在作用期内的扩展方法AsQueryable,该方法应能返回一个可查询的类型;
4. 检查该类型上是否有一个名为AsEnumerable的实例方法,该方法应能返回一个可查询的类型;
5. 检查该类型上是否有一个在作用期内的扩展方法AsEnumerable,该方法应能返回一个可查询的类型;
 
    如果编译器在任一步中找到了一个匹配的方法,它就会插入一个对该方法的调用。当System.Data这个namespaceImport了以后,编译器在第5步为DataTable找到了一个匹配的,然后为你插入对AsEnumerable的调用。结果,你就可以象这个从101 LINQ Sampleshttp://msdn.microsoft.com/en-us/vbasic/bb688088.aspx)中拿来的示例那样编写对DataSet操作的LINQ:
Dim customers = TestDS.Tables("Customers")
 
Dim franceCustomers = From cust In customers _
                              Where cust!Country = "France" _
                              Select cust
   这里的意思,是你可以通过提供一个能够返回某种可查询的东西的AsEnumerable扩展方法来使得你的类型可以被LINQ使用。
   注意,对于强类型的Dataset,你不需要去调用AsEnumerable,因为它们继承自TypedTableBase(Of T),而后者则实现了IEnumerable。这里VS2008中的一个新类型;在VS2005中,Dataset Designer将会生成从DataTable继承的代码,然后自己去显示的实现IEnumerable

posted on 2008-10-28 14:10:20 by VBCTI  评论(5) 阅读(2428)

从 SQL 到 LINQ, 第7部分: 合并, TOP, 子查询 (Bill Horst)

[原文作者]Bill Horst
[原文地址]Converting SQL to LINQ, Part 7: UNION, TOP, Subqueries (Bill Horst)

    本文假设您已阅读了本系列中此前发表的文章:

          SQL LINQ, Part 1: 基础(Bill Horst)

          SQL LINQ, Part 2: FROM SELECT(Bill Horst)

          Converting SQL to LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators

          Converting SQL to LINQ, Part 4: Functions

Converting SQL to LINQ, Part 5: GROUP BY and HAVING

Converting SQL to LINQ, Part 6: Joins

 

    本文中我们将讨论一下合并, TOP 和子查询. 下个星期, 我打算更深入地介绍一下LEFT, RIGHT FULL OUTER JOIN. 如果你想了解关于转换SQLLINQ的其他问题, 请回复本文.

 

合并(UNION)

 

SQL, 一个UNION子句合并两个SELECT查询结果为一个数据集. VB LINQ, 可以通过在一个查询中调用Union方法, 并把第二个查询传递给这个方法可以得到相同的结果. Intersect方法也一样可以这样调用, 它返回的是两个查询的交集. Except方法返回的结果只包括那些在第一个查询中出现但不在第二个查询中出现记录.

 

SQL

SELECT CustomerID ID FROM CustomerTable

UNION

SELECT OrderID ID From OrderTable

 

 

VB

(From Contact In CustomerTable _

 Select ID = Contact.CustomerID).Union(From Shipment In OrderTable _

                                       Select ID = Shipment.OrderID)

 

 

TOP

 

SQLTOP运算符返回一个查询结果的前n. VB LINQ中的Take子句可以达到同样效果. 下面的例子详细描述了Take的功能, 同时使用了一些其他相关的子句.

 

SQL

SELECT TOP 10 * FROM CustomerTable ORDER BY CustomerID

 

 

VB

From Contact In CustomerTable Order By Contact.CustomerID Take 10

 

 

Take/Skip/While

 

    Take子句作用于位于它前面的子句, 并指定一个表示要 或返回多少条结果的数字. 查询结果中其他的记录会被丢弃.

 

    Skip子句指定了一个数字, 表示要忽略查询结果中 多少条记录. 当前面子句的结果被传递给Skip子句后, 它只返回除了前n条记录外的其他结果.

 

    Take While子句指定一个条件, 并从一个查询结果的开头获取记录, 直到这个条件为False. 

 

    Skip While子句指定一个条件, 并从一个查询结果的开头获取记录, 它会忽略前面的记录, 直到这个条件为False.

 

   举几个具体的例子, 下面的几个查询返回如下的结果:

 

VB

 

Dim digits = New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

 

Dim AllDigits = From int In digits

 

返回结果:

        0        3        6        9

        1        4        7

        2        5        8

 

 

SKIP

 

Dim SkipFirstTwo = From int In digits Skip 2

 

返回结果:

        2        5        8

        3        6        9

        4        7

 

 

TAKE

 

Dim TakeFirstTwo = From int In digits Take 2

 

返回结果:

        0

        1

 

 

SKIP and TAKE together

 

Dim SkipTwoTakeFive = From int In digits Skip 2 Take 5

 

返回结果:

        2        5

        3        6

        4

 

 

 

SKIP WHILE

 

Dim SkipUntilFour = From int In digits Skip While int Mod 5 <> 4

 

返回结果:

        4        7

        5        8

        6        9

 

 

TAKE WHILE

 

Dim TakeUntilThree = From int In digits _

                     Take While int = 0 OrElse int Mod 3 <> 0

 

返回结果:

        0        2

        1

 

 

子查询

 

    SQLSELECT语句可以包含子查询, 就是指一个查询使用了另一个查询的结果. VB LINQ, 子查询可以出现在任何允许使用LINQ表达式的地方, SQL子查询一样, 你可以使用括号来避免语法中的歧义.

 

SQL

SELECT OrderID, OrderDate

FROM OrderTable

WHERE CustomerID = (SELECT CustomerID

                    FROM CustomerTable

                    WHERE City = “Seattle”)

 

 

VB

From Shipment In OrderTable _

Where (From Contact In CustomerTable _

       Where Contact.City = “Seattle” _

       Select Contact.CustomerID).Contains(Shipment.CustomerID) _

Select Shipment.OrderID, Shipment.OrderDate

 

 

    还要注意的是, 因为一个查询返回的是IEnumerable, 所以你还可以对查询结果进行查询:

 

VB

Dim SeattleOrders = From Contact In CustomerTable _

                    Join Shipment In OrderTable _

                    On Contact.CustomerID Equals Shipment.CustomerID _

                    Where Contact.City = “Seattle”

 

Dim FilteredOrders = From Shipment In SeattleOrders _

                     Select Shipment.OrderID, Shipment.OrderDate

 

 

我很有兴趣知道你们对主题的看法. 下次, 我会仔细地讨论一下LEFT/RIGHT/FULL OUTER JOIN.

-      Bill Horst, VB IDE Test

posted on 2008-01-28 13:13:00 by VBCTI  评论(2) 阅读(6041)

从 SQL 到 LINQ, 第6部分: 联接 (Bill Horst)

[原文作者]Bill Horst

[原文链接]Converting SQL to LINQ, Part 6: Joins (Bill Horst)

 

本文假设您已阅读了本系列中此前发表的文章:

          SQL LINQ, Part 1: 基础(Bill Horst)

          SQL LINQ, Part 2: FROM SELECT(Bill Horst)

          Converting SQL to LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators

          Converting SQL to LINQ, Part 4: Functions

          Converting SQL to LINQ, Part 5: GROUP BY and HAVING

 

本文将讨论一下交叉联接Cross Join, 内联接Inner Join, 自然联接Natural Join 和外(/)联接 Outer (Left/Right) Join.

 

联接

 

在一个SQL SELECT语句中查询一个以上的数据集(例如:)是比较常见的. 把多个表中的信息集中在一起就叫做联接, 而在SQLLINQ中有好几种不同的联接.

 

交叉联接

 

最简单的连接是交叉联接, 又叫笛卡尔积, 是针对两个数据集合的多对多的联接, 一个数据集中的每一条记录与另一个数据集中的每条记录都进行连接. 在一个SQL SELECT语句中, 要实现交叉联接只要在FROM子句中指定一个以上的表就可以了. VB LINQ, 可以用相同的方式实现, 如下所示:

 

SQL

SELECT CustomerTable.Name, OrderTable.OrderDate

FROM CustomerTable, OrderTable

 

 

VB

From Contact In CustomerTable, Shipment In OrderTable _

Select Contact.Name, Shipment.OrderDate

 

 

内联接

 

内联接是一对一的联接, 一个数据集中的记录根据两个数据集中特定的相同字段与另一个数据集中的记录做匹配. 在一个SQL SELECT语句中, 第二个数据集在INNER JOIN子句中指定, 匹配条件在ON子句中指定. 与此类似, VB LINQ联接中, 第二个数据集在Join中指定, On子句则用来指定Equals运算符与哪个字段相匹配.

 

SQL

SELECT Contact.Name, Shipment.OrderID

FROM CustomerTable Contact

INNER JOIN OrderTable Shipment

ON Contact.CustomerID = Shipment.CustomerID

AND Contact.Zip = Shipment.ShippingZip

 

 

VB

From Contact In CustomerTable

Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

And Contact.Zip Equals Shipment.ShippingZip _

Select Contact.Name, Shipment.OrderID

 

 

上面的例子是一个对等联接, 意味着用一个相等运算符联接两个表的信息. 这是On子句中唯一允许使用的运算符, 所以要想实现其他的联接运算符(例如:小于), 你需要使用一个带Where子句的交叉联接.

 

SQL

SELECT Contact.Name, Shipment.OrderID

FROM CustomerTable Contact

INNER JOIN OrderTable Shipment

ON Contact.CustomerID < Shipment.CustomerID

 

 

VB

From Contact In CustomerTable, Shipment In OrderTable _

Where Contact.CustomerID < Shipment.CustomerID

Select Contact.Name, Shipment.OrderID

 

 

自然联接

 

自然联接也是一对一的联接, 在自然联接中一个数据集中的记录依据两个数据集中所有的相同字段(具有相同的名称)与另一个表中的记录做匹配. 在一个SQL SELECT语句中, 第二个数据集可以在NATURAL JOIN子句中指定, 而用来联接的匹配条件是隐含的. VB LINQ中没有和自然联接直接对应的语法, 所以要实现它的最好方法是创建一个内联接并在On子句中手动指定所有相同字段的相等关系. SQL的自然联接相比, 这显得有点冗长, 但理解起来比较容易.

 

SQL

SELECT * FROM CustomerTable

NATURAL JOIN OrderTable

 

 

VB

From Contact In CustomerTable _

Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _
And Contact.Phone Equals Shipment.Phone

 

 

(/)联接

 

外联接(也被称为左联接或右联接), 是一种一对多的联接, 一个数据集中的每条记录根据两个数据集的相同字段可以与另一个数据集中的多条记录相匹配. 在一个SQL SELECT语句中, 第二个数据集在LEFT JOINRIGHT JOIN子句中指定, 用来联接两个数据集的匹配条件在ON 子句中指定. LEFT JOIN, 第一个()数据集中的每条记录根据匹配条件与第二个表中所有满足匹配条件的记录相联接. 第一个数据集中的所有记录都会出现在结果集中, 不论第二个数据集中有没有与之匹配的记录. 这与RIGHT JOIN相反, 在外联接中所有第二个()数据集中的记录都会出现在结果集中, 并尽可能与第一个数据集中的任何匹配的记录相联接.

 

VB LINQ, 与外连接最相似的结构是分组联接. 在分组联接中, Group Join子句指定了第二个数据集, 并在On子句中提供匹配条件, 这与本文前面描述的联接(内联接)很相像. VB LINQ中还有一个Into子句, 它可以用来指定对每个分组执行什么样的集合运算, 就像是在一个像前面Group Join那样的子句中.

 

SQL LEFT JOIN类似, 分组连接中第一个数据集的每个成员, 与第二个数据集中所有和它相匹配的记录相联接. 再次提醒一下, 如果第二个数据集中没有任何记录与第一个数据集中的某条记录相匹配, 这条记录仍然会出现在结果集中.

 

SQL

SELECT CustomerTable.Name, SUM(OrderTable.Cost) Sum

FROM CustomerTable

LEFT JOIN OrderTable

ON CustomerTable.CustomerID = OrderTable.CustomerID

GROUP BY CustomerTable.Name

 

 

VB

From Contact In CustomerTable _

Group Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

Into Sum(Shipment.Cost) _

Select Contact.Name, Sum

 

 

实现RIGHT JOIN的最好方式是利用这个Group Join子句, 但需要颠倒其中的表(把后一个表作为第一个).

 

一个比较常见的情况是, 需要使用外联接但不需要进行集合运算. 像上面的示例那样使用Group关键字, 会导致结果被分为一连串大小不等的分组, 下面这个例子可能是VB LINQ中与不需要集合运算的外联接最类似的语法了.

 

SQL

SELECT *

FROM CustomerTable Contact

LEFT JOIN OrderTable Shipment

ON Contact.CustomerID = Shipment.CustomerID

 

 

VB

From Contact In CustomerTable _

Group Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

Into Group

 

 

这些分组联接的例子可能没有涵盖你可能会遇到的LEFT JOIN RIGHT JOIN 的所有情况, 但相信它们会给你一个创建与现有SQL查询相对应的LINQ查询的基本思路.

 

下个星期, 我打算做一个百宝袋”, 主题包括合并(UNION), TOP 和子查询.

 

如果你有任何其他的SQL SELECT语句想要转换到LINQ, 请为本文添加一个关于它回复.

 

-      Bill Horst, VB IDE 测试

posted on 2008-01-28 13:12:00 by VBCTI  评论(2) 阅读(4866)

从SQL 到LINQ, 第5部分: GROUP BY 和 HAVING (Bill Horst)

[原文作者]Bill Horst
[
原文地址]Converting SQL to LINQ, Part 5: GROUP BY and HAVING (Bill Horst)

    本文假定您已阅读过本系列中此前发表的文章:

          SQL LINQ, Part 1: 基础(Bill Horst)

          SQL LINQ, Part 2: FROM SELECT(Bill Horst)

          Converting SQL to LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators

          Converting SQL to LINQ, Part 4: Functions

 

    本文将讨论GROUP BYHAVING子句.

 

GROUP BY

 

    一个SQL GROUP BY 子句使你能够依据特定的字段把记录分组, 从而可以一次处理整个分组.   一个LINQ语句也可以包含一个Group By子句, 但语法有所不同. 下面是一个不正规 (也不完整) 的语法表达式:

 

VB Group By

Group [{optional list of fields}] By {list of fields} _

Into {list of aggregate expressions}

 

 

在这个语法中列出来的所有表达式都可以有别名, 并且当一个标识不能被确定时必须使用别名. 一般说来, 子句首先是一个”Group By”, 其后有一个用来分组的字段的列表; 接着是一个 ”Into”, 其后是要进行集合计算的集合表达式. 例如, 下面的查询计算发送到每个邮政编码的总运输费用和平均运输费用:

 

VB

From Shipment In OrderTable _

Group By Shipment.ShippingZip _

Into Total = Sum(Shipment.Cost), Average(Shipment.Cost)

 

    这个查询为数据表中存在的每个邮政编码返回3个值: 邮政编码, 运输费用总计和平均运输费用.

 

    可选地, "Group” "By” 关键字之间可以指定字段来减少某些字段中包含的信息. 这可以被看作是一个内置的, Into子句之前的Select子句:

 

VB

From Shipment In OrderTable _

Group OrderCost = Shipment.Cost By Shipment.ShippingZip _

Into Total = Sum(OrderCost), Average(OrderCost)

 

作为对集合表达式的补充, Into子句也可以包含 “Group” 关键字, 它的作用是使分组中的每个记录成为一个数组成员. 下面这个查询为数据中存在的每个邮政编码和订货日期的组合返回两组值, 邮政编码和订货日期, 加上一个包含分组中所有记录的数组.

 

VB

From Shipment In OrderTable _

Group By Zip = Shipment.ShippingZip, Shipment.OrderDate _

Into Group

 

如果"Group” " By之间没有指明字段, 如上所示, 则返回的数组中包含所有字段. 下面这个查询为数据中存在的每个邮政编码和订货日期的组合, 返回分组中每条记录的邮政编码和订货日期, 以及ID和支出两个字段组成的数组.

 

VB

From Shipment In OrderTable _

Group ID = Shipment.OrderID, Shipment.Cost By _

    Zip = Shipment.ShippingZip, Shipment.OrderDate _

Into Group

 

    因为语法确实很复杂, 我已给出了好几个例子, 现在我们开始看一下如何转换各种包含GROUP BY 子句的SQL语句到VB. 下面是一个例子:

 

SQL

SELECT OrderDate Date_Of_Order, SUM(Cost) Daily_Total

FROM OrderTable

GROUP BY Date_Of_Order

 

 

VB

From Shipment In OrderTable _

Group By Date_Of_Order = Shipment.OrderDate _

Into Daily_Total = Sum(Shipment.Cost)

 

 

Having

 

    Having 是另一个可以在查询结果中指定分组条件的SQL子句. VB中没有类似的子句, 所以用VB LINQ实现它的最好的方式是在Group By子句后使用一个Where子句, 如下所示:

 

SQL

SELECT OrderDate Date_Of_Order, SUM(Cost) Total_Cost

FROM OrderTable

GROUP BY Date_Of_Order

HAVING SUM(Cost) > 1000

 

 

VB

From Shipment In OrderTable _

Group By Date_Of_Order = Shipment.OrderDate _

Into Total_Cost = Sum(Shipment.Cost)

Where Total_Cost > 1000

 

 

    在下一篇文章中, 我打算讨论各种各样的联接.

- Bill Horst, VB IDE Test

posted on 2008-01-28 13:10:00 by VBCTI  评论(1) 阅读(5551)

从SQL 到 LINQ, Part 4: 函数 (Bill Horst)

[原文作者]: Bill Horst

[原文链接]: Converting SQL to LINQ, Part 4: Functions (Bill Horst)

 

在看这篇文章之前,我假定你已经读过了:

SQLLINQPart 1:基础

SQLLINQPart 2FROMSELECT

SQLLINQPart 3DISTINCT, WHERE, ORDER BY 操作符

 

这篇文章讨论的是标量函数(scalar functions)和聚合函数(aggregate functions)。

 

函数

SQLSELECT子句经常会涉及到函数,包含标量函数和聚合函数。一个聚合函数针对的是select出来的一组记录,而标量函数针对的则是其中的个体。我们可以利用VB LINQ表达式实现这两种操作-但是,方法有所不同。

 

标量函数(Scalar Functions

标量函数不论参数如何操作的都是单个记录。他们可以在SQL查询的不同位置出现,比如SELCET子句。虽然标量函数会根据系统的不同而有所不同,但是我们总可以使用类似的VB方法在LINQ语句中进行模拟。如果在LINQSelect子句中使用标量函数,你可能也需要指定一个别名(FirstThreeLetters, CurrentTime)。

 

SQL

SELECT LEFT(ItemName, 3) FirstThreeLetters, NOW() CurrentTime

FROM OrderTable

 

 

VB

From Shipment In OrderTable _

Select FirstThreeLetters = Left(Shipment.ItemName, 3), CurrentTime = Now

 

 

在上面的例子中,LeftNowVB已有的方法(在Microsoft.VisualBasic.dll里定义)。其实大多数SQL支持的标量方法都可以在VB中找到,即使你想调用的方法在VB里还不存在,你可以自己去定义它。但是,用户自定义的方法不能在数据库查询中使用,在运行时系统会抛出异常。在下面的例子中,MyFunction就是一个自定义的方法。

 

VB

From Shipment In OrderTable _

Select MyFunction(Shipment.Cost, Shipment.ShippingZip)

 

 

聚合函数(Aggregate Functions

聚合函数操作的是整个集合,并返回一个值。在SQL语句中,他们可以出现在SLECT子句里。而在LINQ中,情况有所不同。

 

一个VB LINQ表达式通常由From子句开始,但是,也可以是Aggregate子句。Aggregate子句和From子句语法一样,一个由Aggregate开始的子句必须以Into子句结束。Into子句是一组带别名的,由逗号分割的,集合函数调用的列表(a comma-delimited list of Aggregate function calls, with aliases that can accompany them)。下面的例子展示了在SQLSELECT语句中如何使用集合函数,以及其在LINQ中的等价操作。

 

SQL

SELECT SUM(Cost) TotalCost, COUNT(*)

FROM OrderTable

WHERE OrderDate > “Sept-29-2007”

 

 

VB

Aggregate Shipment In OrderTable _

Where Shipment.OrderDate > #9/29/2007# _

Into TotalCost = Sum(Shipment.Cost), Count()

 

 

下次,我们讨论GROUP BY HAVING

posted on 2008-01-14 12:22:00 by VBCTI  评论(2) 阅读(5264)

从SQL到LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators (Bill Horst)

[原文作者]: Bill Horst

[原文链接]: Converting SQL to LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators (Bill Horst)

 

在看这篇文章之前,我假定你已经读过了:

SQLLINQPart 1:基础

SQLLINQPart 2FROMSELECT

 

继续我们的话题,这次我将涉及的主题是DISTINCT, WHERE ORDER BY相关的内容。

 

DISTINCT

 

SQLSLECT语句可以指定DISTINCT标识符以去除所有重复的记录。在LINQ表达式里,Distinct不是从属与Select的标识符,而是一个单独的子句-这意味着Distinct可以出现在任意子句后面,并返回去除重复记录前面子句(在下面的例子里是Select)的结果。下面两个语句得到的是相同的结果:

 

SQL

SELECT DISTINCT Name, Address

FROM CustomerTable

 

 

VB

From Contact In CustomerTable _

Select Contact.Name, Contact.Address _

Distinct

 

 

WHERE

 

SQL非常相似,LINQ允许你使用Where子句根据一定的条件筛选记录。你可以使用任意合法的VB布尔表达式。

 

SQL

SELECT * FROM CustomerTable

WHERE State = “WA”

 

 

VB

From Contact In CustomerTable _

Where Contact.State = “WA”

 

 

操作符

 

SQLWHERE子句可以包含AND这样的操作符,LINQ也允许类似的用法。

 

SQL

SELECT * FROM CustomerTable

WHERE City = “Seattle” AND Zip = “98122”

 

 

VB

From Contact In CustomerTable _

Where Contact.City = “Seattle” And Contact.Zip = “98122”

 

 

即使有些操作符不能完全等价,我们仍然可以模拟。例如BETWEEN

 

SQL

SELECT * FROM OrderTable

WHERE OrderDate BETWEEN ‘Sept-22-2007’ AND ‘Sept-29-2007’

 

 

VB

From Shipment In OrderTable _

Where (Shipment.OrderDate > #9/22/2007#) _

    And (Shipment.OrderDate < #9/29/2007#)

 

 

ORDER BY

 

LINQ也提供了类似SQL ORDER BY子句的表达式,它允许我们使用一个由逗号隔开的列表来指定得到结果的排序依据。我们可以使用任意合法的VB表达式,而并不一定要用Select出来的名字。

 

SQL

SELECT * FROM CustomerTable

ORDER BY Phone

 

 

VB

From Contact In CustomerTable _

Order By Contact.Phone

 

 

ASC/DESC

 

SQLORDER BY子句可以使用ASCDESC关键字来指定升序和降序。VB使用的对应的关键字是Ascending Descending,如果没有指定,默认升序。

 

SQL

SELECT * FROM CustomerTable

ORDER BY Phone ASC, Name DESC

 

 

VB

From Contact In CustomerTable _

Order By Contact.Phone Ascending, Contact.Name Descending

 

 

到目前为止,我们应该已经可以将基本的SQL查询写成LINQ代码。下一次,我会谈到函数-包含ScalarAggregate

 

-      Bill Horst, VB IDE Test

 

posted on 2008-01-03 17:21:00 by VBCTI  评论(4) 阅读(6571)

从SQL 到 LINQ, Part 2: FROM 和 SELECT(Bill Horst)

[原文作者]: Bill Horst

[原文链接]: Converting SQL to LINQ, Part 2: FROM and SELECT (Bill Horst)

 

在看这篇文章之前,我假定你已经读过了SQLLINQPart 1:基础

 

为了让代码示例更清晰,我修改了下列名字:

·         Customers -> CustomerTable

·         Orders -> OrderTable

·         cust -> Contact

·         CustomerName -> ContactName

·         ID -> ContactID

 

欢迎你们的任何反馈和建议,你们的意见可以使以后的文章更清晰更有用。

 

好,现在开始讨论具体的子句(clauses),我们将从最基础的FROMSELECT开始。

 

FROM

 

SQLSELECT语句由SELECT子句开始,并且紧跟着一个FROM子句。而VB查询表达式则由From子句(或者Aggregate子句,我们稍后讨论)开始。一个基本SQLFROM子句指定了一个要操作的表,一个LINQFrom子句指定了一个我们要操作的对象(CustomerTable)。这个对象可以表示“已在内存中的”(“In-Memory”)数据:比如一个SQL表,或者XML信息。因为使用这样的数据比较简单,我的例子也采用了”In-Memory”的数据。除了这个数据对象,VBFrom子句还包含了一个指定当前“行”(Contact)别名的标识符。

 

如果要选择所有的列,在SQL中我们需要使用”*”,而在VB中,我们不需要附加任何东西,From子句默认返回所有的内容。

 

SQL

SELECT *

FROM CustomerTable

 

 

VB

From Contact In CustomerTable

 

 

FROM里的别名(alias)

 

SQL允许你在FROM子句中指定一个表的别名,LINQ同样允许我们这样做。

 

SQL

SELECT Contact.CustomerID, Contact.Phone

FROM CustomerTable Contact

 

 

VB

From Contact In CustomerTable

Select Contact.CustomerID, Contact.Phone

 

 

SELECT

 

SQLSELECT语句由一个包含要select的内容的列表开始(Name, CustomerID) 类似的,LINQ也允许你指定要select的内容,并将结果包装成一个匿名类型(anonymous type)返回。你指定的内容并不一定要是From子句指定对象的一部分,你可以指定任意合法的VB表达式(比如34)。如果成员的名字不能够被推断,你必须为其指定一个别名(见下面的“SELECT里的别名”)。

 

SQL

SELECT Name, CustomerID

FROM CustomerTable

 

 

VB

From Contact In CustomerTable

Select Contact.Name, Contact.CustomerID

 

 

SELECT里的别名

 

SQL允许SELCT子句的成员有别名(ContactName, ContactID),我们可以在查询语句的其它子句中使用这些别名。LINQ也允许别名,并且你可以在所有使用这个查询结果的代码中使用它们。

 

SQL

SELECT Name ContactName, CustomerID ContactID

FROM CustomerTable

 

 

VB

From Contact In CustomerTable

Select ContactName = Contact.Name, ContactID = Contact.CustomerID

 

 

下次我打算讲到DISTINCT, WHERE, ORDER BY 和运算符。

- Bill Horst, VB IDE Test

posted on 2007-12-26 14:26:00 by VBCTI  评论(3) 阅读(4760)

从SQL 到 LINQ, Part 1: 基础(Bill Horst)

[原文作者]: Bill Horst

[原文链接]: Converting SQL to LINQ, Part 1: The Basics

你可能已经知道了,VBLINQ指令允许使用类SQL语法的查询。LINQ的语法并不和SQL的语法完全一致,所以如果你现在已经在用SQL或者熟悉SQL查询的话,你可能会想把已经存在的SQL查询转化为LINQ

这篇文章就是“从SQLLINQ”系列的第一篇。在这篇文章里,我想让大家对SQLLINQ的区别有一个基本的理解,下次我们会涉及到具体的语言架构。

 

假定

 

在接下来的例子, SQL代码会涉及到两个tableCustomersOrdersVB代码会用到与之同名的两个对象,他们的类型分别是IEnumerable(Of Customer)IEnumerable(Of Order)。我还会用到两个类,同样是CustomerOrder,如下:

Class Customer

    Public CustomerID As Integer

    Public Name As String

    Public Phone As String

    Public Address As String

    Public City As String

    Public State As String

    Public Zip As String

End Class

 

Class Order

    Public OrderID As Integer

    Public CustomerID As Integer

    Public Cost As Single

    Public Phone As String

    Public OrderDate As DateTime

    Public ShippingZip As String

    Public ItemName As String

End Class

 

基本语法

 

LINQ支持SQL SELECT语句,而不支持其他的,比如CREATE, INSERT, UPDATE DELETE。你可以认为SQL SELECT语句的基本语法是一系列的“子句”(clauses),其中的第一个是SELECT子句。

sqlSelectClause [ sqlClause1 [ sqlClause2 [ ... ] ] ]

 

SQL的语法可能根据不同的版本有所差异,下面是一个例子:

SQL

SELECT Name CustomerName, CustomerID ID

FROM Customers

ORDER BY ID

 

VB LINQ表达式的基本语法也是一系列的子句,不同的是第一个是From子句(或者Aggregate子句,我们稍后会讨论)。

linqFromClause [ linqClause1 [ linqClause2 [ ... ] ] ]

 

比如:

VB

From cust In Customers _

Select CustomerName = cust.Name, ID = cust.CustomerID _

Order By ID

 

我刚才用了“VB LINQ表达式”的说法是因为前面的“LINQ查询”不是一个完整的语句。虽然SQL语句可以单独出现,但是LINQ查询在语法上和表达式“3 * 4”一样 - 它不是一个完整的语句,所以我们要使它完整。一个VB的完整的LINQ查询的语句看起来像这样:

VB

Dim SortedCustomers = From cust In Customers _

                      Select CustomerName = cust.Name, ID = cust.CustomerID _

                      Order By ID

 

从概念上说,LINQ查询的每个子句操作的都是IEnumerable(Of T)类型并且返回的也是IEnumerable(Of T)类型”(其中的两个T并不一定要相同)。查询子句和SQL子句是基本类似的(比如SELECT, ORDER BY),所以你可以一个子句一个子句地将SQL查询转化成LINQ。在上面的例子里,这些子句出现的顺序稍有不同,而且有些语法上的差异,但是你可以看到,他们非常类似。

还要注意的一点是,SQL语法允许在子句间直接换行,而在VB里,换行需要在每行最后加上下划线(_)去告诉编译器下一行仍然是当前的表达式。

这篇文章只是一个泛泛的说明,但我会在以后讲到更为具体的内容。我打算涉及以下条目:

  • FROM and SELECT
  • DISTINCT, WHERE, ORDER BY, Operators
  • Functions (Scalar and Aggregate)
  • GROUP By and HAVING
  • Joins
  • UNION, TOP and Subqueries

- Bill Horst, VB IDE Test

posted on 2007-12-21 14:09:00 by VBCTI  评论(7) 阅读(5738)

Powered by: Joycode.MVC引擎 0.5.2.0