学习 SQL 到 LINQ(可视化表示)






4.88/5 (102投票s)
讨论了将 SQL 查询转换为 LINQ 查询的可视化表示。
引言
许多开发人员在转向新的 LINQ to SQL 时,发现用 C# 编写 SQL 查询以使用 LINQ 查询数据非常困难。LINQ 是一种集成到 C# 中的查询语言,用于从 ObjectCollect
、SQL、XML 等查询数据。在开始阅读本文之前,建议先了解 LINQ 支持的功能。
在本文中,我将讨论基本的 SQL 查询以及与 SQL 查询类似的 LINQ 查询,并附带 LINQ 查询的可视化表示。在开始讨论之前,这是我用于本文的表结构。
注意:在本文中,所有 LINQ 查询均在 LINQPAD 应用程序中执行。
LINQ 查询列表
情况 1:Select
从 user 表中获取所有用户的所有列的 SQL 查询将是:
SELECT * FROM [User]
执行上述操作的 LINQ 查询是:
var user = from u in Users
select u;
这是您编写的从 user 表获取数据的 LINQ 查询的图形表示 breakdown。
情况 2:Select(带列)
这种情况与上面类似,但不同之处在于我们不选择所有列;相反,我只选择两列:FirstName
和 LastName
。选择仅两列的所有行的 SQL 查询是:
Select FirstName, LastName from [User]
现在是 LINQ 查询:
from u in Users
select new
{
u.FirstName,
u.LastName
};
因此,您需要创建一个新的匿名类型来仅从 user 对象中获取 FirstName
和 LastName
。此查询的图形表示如下:
情况 3:过滤选定的数据
对于整数数据
要对选定的数据应用过滤器,我们使用带有列值的 WHERE
子句,因此 SQL 查询将是:
Select firstname,LastName from [User] where id = 3
在 LINQ 中,我们也需要使用 WHERE
子句,因此查询将是:
from u in Users
where u.Id ==3
select new
{
u.FirstName,
u.LastName
}
此图形表示显示了与过滤数据相关的 LINQ 查询的 breakdown。
对于字符串数据
为了过滤字符串,我们使用 LIKE
。
SELECT [Id], [FirstName], [LastName], [Email],
[DisplayName], [Address1], [Address2], [Password], [Role]
FROM [User]
WHERE [Email] LIKE '%pranay%'
或
SELECT [Id], [FirstName], [LastName], [Email],
[DisplayName], [Address1], [Address2], [Password], [Role]
FROM [User]
WHERE [Email] LIKE 'pranay%'
要对字符串数据类型应用过滤器,您需要使用 C# 中可用的 Contains
或 StartWith
函数,这样它就会生成与上述 SQL 查询相同的结果。
from u in Users
where u.Email.Contains ("pranay")
select u
或
from u in Users
where u.Email.StartsWith ("pranay")
select u
使用字符串字段过滤的 LINQ 查询的图形表示。
情况 4:连接两个表
内连接(Inner Join)
内部连接是我们如何获取两个表之间的公共记录,即表中的相关记录。以下是内部连接的 SQL 查询:
SELECT [User].[Id], [FirstName], [LastName], [UserId], [MobileNo]
FROM [User]
INNER JOIN
[UserClients]
ON [User].[id] = [UserId]
LINQ 使用 Join
关键字和 Equals
来连接两个集合,从而执行相同的操作。
var user = from u in Users
join uc in UserClients on u.Id equals uc.UserId
select new {
u.Id,
u.FirstName,
u.LastName,
uc.MobileNo,
uc.imeiNO,
uc.Id,
};
下面显示了 LINQ 查询的内部连接的图形表示。如您所见,User connection 基于 On.. Equals
中的条件添加到 UserClients。
外部连接
外部连接是我们如何获取两个表之间的公共记录,即表中的相关记录;来自左表的所有记录,如果在右表中未找到,则会获得 null 值。外部连接的 SQL 查询将如下所示:
SELECT [t0].[Id], [FirstName], [LastName],
[UserId] AS [UserId], [MobileNo] AS [MobileNo]
FROM [User] AS [t0]
LEFT OUTER JOIN [UserClients] ON ([t0].[id]) = [UserId]
在 LINQ 中,要实现外部连接,您需要使用 DefaultIfEmpty()
函数,如下所示:
var user = from u in Users
join uc in UserClients on u.Id equals uc.UserId
into myuserwithclient
from m in myuserwithclient.DefaultIfEmpty()
select new {
u.Id,
u.FirstName,
u.LastName,
m.UserId,
m.MobileNo
};
外部连接 LINQ 查询的图形表示与内部连接相同,但 DefaultIfEmpty()
函数还有一步。
情况 5:排序数据
在 SQL 中,要对获取的数据进行排序,我们需要应用 ORDER BY
子句以及 ASC
或 DESC
关键字,因此 SQL 查询将是:
--Ascending
Select * from [User] order by firstName
或
--Descending
Select * from [User] order by firstName desc
LINQ 使用 ORDER BY
结合 ASCENDING
和 DESCENDING
关键字,因此最终的 LINQ 查询将是:
//Ascending
var user = from u in Users
orderby u.FirstName
select new
{
u.FirstName,
u.LastName
}
或
//Descending
var user = from u in Users
orderby u.FirstName descending
select new
{
u.FirstName,
u.LastName
};
这是 LINQ 查询的图形 breakdown。
情况 6:分组数据
选定数据的分组允许执行聚合函数,如 SUM
、MAX
、MIN
、COUNT
等。要在 SQL 中对数据进行分组,您需要使用 GROUP BY
子句,但需要记住的是,您需要在 group by
子句中包含 select 列表列,否则您将收到语法错误。
SELECT COUNT(*) AS [test], [UserId]
FROM [UserClients]
GROUP BY [UserId]
LINQ 使用 Group ... By
来分组数据,因此查询如下所示:
var user = from u in UserClients
group u by u.UserId into c
select new
{
t1 = c.Key,
tcount = c.Count()
};
注意:在 LINQ 中对对象集合应用 group by 后,您的 group by 列将转换为键列,您可以在上面的 LINQ 查询 UserId
中看到。Group...By
LINQ 查询的图形 breakdown 是:
情况 7:使用 IN 和 NOT IN 子句过滤数据
大多数开始使用 LINQ 查询的开发人员在不得不使用 LINQ 编写 IN
和 NOT IN
查询时会感到困惑。以下是 SQL 查询:
//IN
SELECT [Id], [UserId], [IMEINo]
FROM [UserClients]
WHERE [UserId] IN (3, 4)
或
//NOT IN
SELECT [Id], [UserId], [IMEINo]
FROM [UserClients]
WHERE [UserId] IN (3, 4)
如上所示,查询使用 IN
和 NOT IN
子句从记录列表中进行过滤。执行此任务的 LINQ 查询利用了 C# 的 Contains
函数,该函数从记录列表中过滤记录。
//IN
int[] chosenOnes = { 3, 4 };
var user = from u in UserClients
where chosenOnes.Contains(u.UserId.Value)
select new { u.id,u.userid, u.ImeiNo};
或
//NOT IN
int[] chosenOnes = { 3, 4 };
var user = from u in UserClients
where !chosenOnes.Contains(u.UserId.Value)
select u;
注意:IN
和 NOT IN
在 LINQ 查询中使用相同的函数,但它只使用一个!(not) 符号。以下是图形表示:
情况 8:按行号过滤数据
我现在将展示如何按分配给记录的行号过滤数据。要在 SQL Server (SQL Server 2005) 中过滤数据,我们使用 RowNumber
函数,然后我们使用 <=
、>=
或 BETWEEN
。以下是 SQL 查询:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [id]) AS [ROW_NUMBER],
[id], [FirstName], [LastName], [Email], [DisplayName],
[Address1], [Address2], [Password], [Role]
FROM [User] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN 11 AND 20
ORDER BY [t1].[ROW_NUMBER]
在上面的查询中,如您所见,ROW_NUMBER()
函数为记录分配一个编号,然后我们可以在外部查询中使用该编号来过滤 11 到 20 之间的数据。LINQ 使用两个函数:
LINQ 查询如下所示:
var users = from u in Users
select u;
var filterUsers= users.OrderBy (p => p.Id).Skip (10).Take(10);
在上面的代码中,我们首先选择数据,然后应用 Skip
和 Take
来获取 11 到 20 条记录之间的数据。以下是图形表示;
最好的例子是当您在使用自定义分页的 grid 控件或 list 控件时。更详细的示例可以在这里看到:LINQ tO SQL GridView (Enhanced GridView)。
情况 9:SQL ISNULL 函数
注意:在此情况下,没有图形表示,我将只展示 LINQ 可以实现的另一个函数。
在继续之前,请阅读以下帖子:
解决方案 1
我们可以使用三元运算符,如以下示例所示,对于 null
值,使用 MobileNo = "N/A"
。
var user = from u in Users
join uc in UserClients on u.Id equals uc.UserId
into myuserwithclient
from m in myuserwithclient.DefaultIfEmpty()
select new {
u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
UserId = m.UserId,
MobileNo = (m.MobileNo == null) ? "N/A" : m.MobileNo
};
解决方案 2
使用特殊合并运算符(??
),如以下示例所示,对于 null
值,使用 MobileNo = "N/A"
。
var user = from u in Users
join uc in UserClients on u.Id equals uc.UserId
into myuserwithclient
from m in myuserwithclient.DefaultIfEmpty()
select new {
u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
UserId = m.UserId,
MobileNo = m.MobileNo == null ?? "N/A"
};
摘要
本文展示了许多 LINQ 查询的可视化表示。希望您喜欢使用 LINQ!