LINQ体验6LINQ to SQL语句之Join和Order By.docx
- 文档编号:8509555
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:11
- 大小:36.81KB
LINQ体验6LINQ to SQL语句之Join和Order By.docx
《LINQ体验6LINQ to SQL语句之Join和Order By.docx》由会员分享,可在线阅读,更多相关《LINQ体验6LINQ to SQL语句之Join和Order By.docx(11页珍藏版)》请在冰豆网上搜索。
LINQ体验6LINQtoSQL语句之Join和OrderBy
Join操作
适用场景:
在我们表关系中有一对一关系,一对多关系,多对多关系等。
对各个表之间的关系,就用这些实现对多个表的操作。
说明:
在Join操作中,分别为Join(Join查询),SelectMany(Select一对多选择)和GroupJoin(分组Join查询)。
该扩展方法对两个序列中键匹配的元素进行innerjoin操作
SelectMany
说明:
我们在写查询语句时,如果被翻译成SelectMany需要满足2个条件。
1:
查询语句中没有join和into,2:
必须出现EntitySet。
在我们表关系中有一对一关系,一对多关系,多对多关系等,下面分别介绍一下。
1.一对多关系(1toMany):
varq=
fromcindb.Customers
fromoinc.Orders
wherec.City=="London"
selecto;
语句描述:
Customers与Orders是一对多关系。
即Orders在Customers类中以EntitySet形式出现。
所以第二个from是从c.Orders而不是db.Orders里进行筛选。
这个例子在From子句中使用外键导航选择伦敦客户的所有订单。
varq=
frompindb.Products
wherep.Supplier.Country=="USA"&&p.UnitsInStock==0
selectp;
语句描述:
这一句使用了p.Supplier.Country条件,间接关联了Supplier表。
这个例子在Where子句中使用外键导航筛选其供应商在美国且缺货的产品。
生成SQL语句为:
SELECT[t0].[ProductID],[t0].[ProductName],[t0].[SupplierID],
[t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
[t0].[UnitsInStock],[t0].[UnitsOnOrder],[t0].[ReorderLevel],
[t0].[Discontinued]FROM[dbo].[Products]AS[t0]
LEFTOUTERJOIN[dbo].[Suppliers]AS[t1]ON
[t1].[SupplierID]=[t0].[SupplierID]
WHERE([t1].[Country]=@p0)AND([t0].[UnitsInStock]=@p1)
--@p0:
InputNVarChar(Size=3;Prec=0;Scale=0)[USA]
--@p1:
InputInt(Size=0;Prec=0;Scale=0)[0]
2.多对多关系(ManytoMany):
varq=
fromeindb.Employees
frometine.EmployeeTerritories
wheree.City=="Seattle"
selectnew
{
e.FirstName,
e.LastName,
et.Territory.TerritoryDescription
};
说明:
多对多关系一般会涉及三个表(如果有一个表是自关联的,那有可能只有2个表)。
这一句语句涉及Employees,EmployeeTerritories,Territories三个表。
它们的关系是1:
M:
1。
Employees和Territories没有很明确的关系。
语句描述:
这个例子在From子句中使用外键导航筛选在西雅图的雇员,同时列出其所在地区。
这条生成SQL语句为:
SELECT[t0].[FirstName],[t0].[LastName],[t2].[TerritoryDescription]
FROM[dbo].[Employees]AS[t0]CROSSJOIN[dbo].[EmployeeTerritories]
AS[t1]INNERJOIN[dbo].[Territories]AS[t2]ON
[t2].[TerritoryID]=[t1].[TerritoryID]
WHERE([t0].[City]=@p0)AND([t1].[EmployeeID]=[t0].[EmployeeID])
--@p0:
InputNVarChar(Size=7;Prec=0;Scale=0)[Seattle]
3.自联接关系:
varq=
frome1indb.Employees
frome2ine1.Employees
wheree1.City==e2.City
selectnew{
FirstName1=e1.FirstName,LastName1=e1.LastName,
FirstName2=e2.FirstName,LastName2=e2.LastName,
e1.City
};
语句描述:
这个例子在select子句中使用外键导航筛选成对的雇员,每对中一个雇员隶属于另一个雇员,且两个雇员都来自相同城市。
生成SQL语句为:
SELECT[t0].[FirstName]AS[FirstName1],[t0].[LastName]AS
[LastName1],[t1].[FirstName]AS[FirstName2],[t1].[LastName]AS
[LastName2],[t0].[City]FROM[dbo].[Employees]AS[t0],
[dbo].[Employees]AS[t1]WHERE([t0].[City]=[t1].[City])AND
([t1].[ReportsTo]=[t0].[EmployeeID])
GroupJoin
像上面所说的,没有join和into,被翻译成SelectMany,同时有join和into时,那么就被翻译为GroupJoin。
在这里into的概念是对其结果进行重新命名。
1.双向联接(Twowayjoin):
此示例显式联接两个表并从这两个表投影出结果:
varq=
fromcindb.Customers
joinoindb.Ordersonc.CustomerID
equalso.CustomerIDintoorders
selectnew
{
c.ContactName,
OrderCount=orders.Count()
};
说明:
在一对多关系中,左边是1,它每条记录为c(fromcindb.Customers),右边是Many,其每条记录叫做o(joinoindb.Orders),每对应左边的一个c,就会有一组o,那这一组o,就叫做orders,也就是说,我们把一组o命名为orders,这就是into用途。
这也就是为什么在select语句中,orders可以调用聚合函数Count。
在T-SQL中,使用其内嵌的T-SQL返回值作为字段值。
如图所示:
生成SQL语句为:
SELECT[t0].[ContactName],(
SELECTCOUNT(*)
FROM[dbo].[Orders]AS[t1]
WHERE[t0].[CustomerID]=[t1].[CustomerID]
)AS[OrderCount]
FROM[dbo].[Customers]AS[t0]
2.三向联接(Therewayjoin):
此示例显式联接三个表并分别从每个表投影出结果:
varq=
fromcindb.Customers
joinoindb.Ordersonc.CustomerID
equalso.CustomerIDintoords
joineindb.Employeesonc.City
equalse.Cityintoemps
selectnew
{
c.ContactName,
ords=ords.Count(),
emps=emps.Count()
};
生成SQL语句为:
SELECT[t0].[ContactName],(
SELECTCOUNT(*)
FROM[dbo].[Orders]AS[t1]
WHERE[t0].[CustomerID]=[t1].[CustomerID]
)AS[ords],(
SELECTCOUNT(*)
FROM[dbo].[Employees]AS[t2]
WHERE[t0].[City]=[t2].[City]
)AS[emps]
FROM[dbo].[Customers]AS[t0]
3.左外部联接(LeftOuterJoin):
此示例说明如何通过使用此示例说明如何通过使用DefaultIfEmpty()获取左外部联接。
在雇员没有订单时,DefaultIfEmpty()方法返回null:
varq=
fromeindb.Employees
joinoindb.Ordersoneequalso.Employeeintoords
fromoinords.DefaultIfEmpty()
selectnew
{
e.FirstName,
e.LastName,
Order=o
};
说明:
以Employees左表,Orders右表,Orders表中为空时,用null值填充。
Join的结果重命名ords,使用DefaultIfEmpty()函数对其再次查询。
其最后的结果中有个Order,因为fromoinords.DefaultIfEmpty()是对ords组再一次遍历,所以,最后结果中的Order并不是一个集合。
但是,如果没有fromoinords.DefaultIfEmpty()这句,最后的select语句写成selectnew{e.FirstName,e.LastName,Order=ords}的话,那么Order就是一个集合。
4.投影的Let赋值(Projectedletassignment):
说明:
let语句是重命名。
let位于第一个from和select语句之间。
这个例子从联接投影出最终“Let”表达式:
varq=
fromcindb.Customers
joinoindb.Ordersonc.CustomerID
equalso.CustomerIDintoords
letz=c.City+c.Country
fromoinords
selectnew
{
c.ContactName,
o.OrderID,
z
};
5.组合键(CompositeKey):
这个例子显示带有组合键的联接:
varq=
fromoindb.Orders
frompindb.Products
joindindb.OrderDetails
onnew
{
o.OrderID,
p.ProductID
}equals
new
{
d.OrderID,
d.ProductID
}
intodetails
fromdindetails
selectnew
{
o.OrderID,
p.ProductID,
d.UnitPrice
};
说明:
使用三个表,并且用匿名类来说明:
使用三个表,并且用匿名类来表示它们之间的关系。
它们之间的关系不能用一个键描述清楚,所以用匿名类,来表示组合键。
还有一种是两个表之间是用组合键表示关系的,不需要使用匿名类。
6.可为null/不可为null的键关系(Nullable/NonnullableKeyRelationship):
这个实例显示如何构造一侧可为null而另一侧不可为null的联接:
varq=
fromoindb.Orders
joineindb.Employees
ono.EmployeeIDequals
(int?
)e.EmployeeIDintoemps
fromeinemps
selectnew
{
o.OrderID,
e.FirstName
};
OrderBy操作
适用场景:
对查询出的语句进行排序,比如按时间排序等等。
说明:
按指定表达式对集合排序;延迟,:
按指定表达式对集合排序;延迟,默认是升序,加上descending表示降序,对应的扩展方法是OrderBy和OrderByDescending
1.简单形式
这个例子使用orderby按雇用日期对雇员进行排序:
varq=
fromeindb.Employees
orderbye.HireDate
selecte;
说明:
默认为升序
2.带条件形式
注意:
Where和OrderBy的顺序并不重要。
而在T-SQL中,Where和OrderBy有严格的位置限制。
varq=
fromoindb.Orders
whereo.ShipCity=="London"
orderbyo.Freight
selecto;
语句描述:
使用where和orderby按运费进行排序。
3.降序排序
varq=
frompindb.Products
orderbyp.UnitPricedescending
selectp;
4.ThenBy
语句描述:
使用复合的orderby对客户进行排序,进行排序:
varq=
fromcindb.Customers
orderbyc.City,c.ContactName
selectc;
说明:
按多个表达式进行排序,例如先按City排序,当City相同时,按ContactName排序。
这一句用Lambda表达式像这样写:
varq=
db.Customers
.OrderBy(c=>c.City)
.ThenBy(c=>c.ContactName).ToList();
在T-SQL中没有ThenBy语句,其依然翻译为OrderBy,所以也可以用下面语句来表达:
varq=
db.Customers
.OrderBy(c=>c.ContactName)
.OrderBy(c=>c.City).ToList();
所要注意的是,多个OrderBy操作时,级连方式是按逆序。
对于降序的,用相应的降序操作符替换即可。
varq=
db.Customers
.OrderByDescending(c=>c.City)
.ThenByDescending(c=>c.ContactName).ToList();
需要说明的是,OrderBy操作,不支持按type排序,也不支持匿名类。
比如
varq=
db.Customers
.OrderBy(c=>new
{
c.City,
c.ContactName
}).ToList();
会被抛出异常。
错误是前面的操作有匿名类,再跟OrderBy时,比较的是类别。
比如
varq=
db.Customers
.Select(c=>new
{
c.City,
c.Address
})
.OrderBy(c=>c).ToList();
如果你想使用OrderBy(c=>c),其前提条件是,前面步骤中,所产生的对象的类别必须为C#语言的基本类型。
比如下句,这里City为string类型。
varq=
db.Customers
.Select(c=>c.City)
.OrderBy(c=>c).ToList();
5.ThenByDescending
这两个扩展方式都是用在OrderBy/OrderByDescending之后的,第一个ThenBy/ThenByDescending扩展方法作为第二位排序依据,第二个ThenBy/ThenByDescending则作为第三位排序依据,以此类推
varq=
fromoindb.Orders
whereo.EmployeeID==1
orderbyo.ShipCountry,o.Freightdescending
selecto;
语句描述:
使用orderby先按发往国家再按运费从高到低的顺序对EmployeeID1的订单进行排序。
6.带GroupBy形式
varq=
frompindb.Products
grouppbyp.CategoryIDintog
orderbyg.Key
selectnew{
g.Key,
MostExpensiveProducts=
fromp2ing
wherep2.UnitPrice==g.Max(p3=>p3.UnitPrice)
selectp2
};
语句描述:
使用orderby、Max和GroupBy得出每种类别中单价最高的产品,并按CategoryID对这组产品进行排序。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LINQ体验6LINQ to SQL语句之Join和Order By LINQ 体验 SQL 语句 Join Order