LINQ做查询是本分,我们看看LINQ的查询吧
这篇文章使用的数据模型如下:

还是上一篇提到的Student表,为了做查询我多添加了几个字段而已。
在自动生成的DataContext中有Students属性,它的类型是Table对应数据库中的Student表,我们的查询对象就是它了。
先来一个最简单的Query
| 1 |
var query = from s in db.Students |
上面的语句可以查询Student表的所有记录,但是它却不同于 SQL语句
| 10 |
FROM [Test].[dbo].[Student] |
query的数据类型是IQueryable ,其字面意思是Student的可查询实例,通过这个query我们可以做很多种查询,当然包括上面的SQL语句。具体这个IQueryable实例会做那种查询和我们后续代码中如何使用它有关系,下面是几个例子:
1. 使用query返回Student表中的记录数,代码如下
| 01 |
using (var writer = new StreamWriter(@"E:\projects.2010\Test\LINQ2SQL_2\linq.sql", false, Encoding.UTF8)) |
| 04 |
using (DbAppDataContext db = new DbAppDataContext()) |
| 08 |
var query = from s in db.Students |
| 12 |
var cn = query.Count(); |
上面query.Count()执行的SQL如下:
| 1 |
SELECT COUNT(*) AS [value] |
| 2 |
FROM [dbo].[Student] AS [t0] |
| 3 |
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319. |
生成的sql语句很规范,取得Student表中的记录数
2.给这个IQuerable添加条件身高大于130cm,然后执行查询
| 01 |
using (var writer = new StreamWriter(@"E:\projects.2010\Test\LINQ2SQL_2\linq.sql", false, Encoding.UTF8)) |
| 04 |
using (DbAppDataContext db = new DbAppDataContext()) |
| 06 |
//设置Log属性,将生成的sql语句保存到文件中 |
| 08 |
var query = from s in db.Students |
| 12 |
foreach (var item in query.Where(s => s.HeightInCm > 132)) |
| 14 |
Console.WriteLine("{0}的身高是{1}cm", item.Name, item.HeightInCm); |
其SQL语句如下:可以看到linq to sql对sql注入攻击有天然的免疫作用,它自动生成的sql语句是参数化的
| 1 |
SELECT [t0].[StudentID], [t0].[Name], [t0].[Hometown], [t0].[Gender], [t0].[Birthday], [t0].[ClassID], [t0].[WeightInKg], [t0].[HeightInCm], [t0].[Desc] AS [Desc] |
| 2 |
FROM [dbo].[Student] AS [t0] |
| 3 |
WHERE [t0].[HeightInCm] > @p0 |
| 4 |
-- @p0: Input Float (Size = -1; Prec = 0; Scale = 0) [132] |
| 5 |
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319.1 |
我们可以对IQueryable附加条件限制,其实添加这个Where后的query和下面的语句是等价的。
| 1 |
var query = from s in db.Students |
| 2 |
where s.HeightInCm > 132 |
那么如果我们的query实例中已经有条件后再加限制会是什么样子的呢,请看3
3. 在query定义是有身高、体重两个查询条件,在使用query时我们又附加了一个Hometown在“多家营”的条件,看下代码和真实执行的sql情况
| 01 |
using (var writer = new StreamWriter(@"E:\projects.2010\Test\LINQ2SQL_2\linq.sql", false, Encoding.UTF8)) |
| 04 |
using (DbAppDataContext db = new DbAppDataContext()) |
| 06 |
//设置Log属性,将生成的sql语句保存到文件中 |
| 09 |
//查询身高大于132并且体重大于30的Student |
| 10 |
var query = from s in db.Students |
| 11 |
where s.HeightInCm > 132 && s.WeightInKg > 30 |
| 14 |
//在query中用Where附加家乡在多家营的记录 |
| 15 |
foreach (var item in query.Where(s => s.Hometown == "多家营")) |
| 17 |
Console.WriteLine("{0}的身高是{1}cm", item.Name, item.HeightInCm); |
SQL:
| 1 |
SELECT [t0].[StudentID], [t0].[Name], [t0].[Hometown], [t0].[Gender], [t0].[Birthday], [t0].[ClassID], [t0].[WeightInKg], [t0].[HeightInCm], [t0].[Desc] AS [Desc] |
| 2 |
FROM [dbo].[Student] AS [t0] |
| 3 |
WHERE "BACKGROUND-COLOR: #ffff00">([t0].[Hometown] = @p0) AND ([t0].[HeightInCm] > @p1) AND ([t0].[WeightInKg] > @p2) |
| 4 |
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [多家营] |
| 5 |
-- @p1: Input Float (Size = -1; Prec = 0; Scale = 0) [132] |
| 6 |
-- @p2: Input Float (Size = -1; Prec = 0; Scale = 0) [30] |
| 7 |
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319.1 |
可以看出后附件的条件并非如我们常规理解附件到条件的最后,而是放到了最前面,这一点有可能对效率造成影响,是需要我们注意的。
通过上面三点可以看出来linq to sql中的IQueryable并非等同于某一个sql语句,其具体要执行的sql语句和具体情况有关系。
在query定义时可以很方便的添加排序规则,可以是一个或者n个,如下语句:
| 1 |
//查询身高大于132并且体重大于30的Student,并按照StudentID升序排序,按照classID降序排序 |
| 2 |
var query = from s in db.Students |
| 3 |
where s.HeightInCm > 132 && s.WeightInKg > 30 |
| 4 |
orderby s.StudentID ascending, s.ClassID descending |
本文完,后续系列会介绍join,多表查询等。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-662702/
,如需转载,请注明出处,否则将追究法律责任。