【网学网提醒】:网学会员为大家收集整理了Linq_to_sql_server基本语法(最新版)提供大家参考,希望对大家有所帮助!
Linqtosqlserver基本语法Where操作适用场景:适用场景:实现过滤,查询等功能。说明:说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句。Where操作包括3种形式,分别为简单形式、关系条件形式、First()形式。下面分别用实例举例下:1.简单形式:1.简单形式:简单形式例如:使用where筛选在伦敦的客户varq=fromcindb.Customerswherec.City=="London"selectc;再如:筛选1994年或之后雇用的雇员:varq=fromeindb.Employeeswheree.HireDate>=newDateTime(1994,1,1)selecte;2.关系条件形式:2.关系条件形式:关系条件形式筛选库存量在订货点水平之下但未断货的产品:varq=frompindb.Productswherep.UnitsInStock<=p.ReorderLevel&;&;!p.Discontinuedselectp;筛选出UnitPrice大于10或已停产的产品:varq=
1
frompindb.Productswherep.UnitPrice>10m||p.Discontinuedselectp;下面这个例子是调用两次where以筛选出UnitPrice大于10且已停产的产品。varq=db.Products.Where(p=>p.UnitPrice>10m).Where(p=>p.Discontinued);3.First()形式:3.First()形式:形式返回集合中的一个元素,其实质就是在SQL语句中加TOP(1)。简单用法:选择表中的第一个发货方。Shippershipper=db.Shippers.First();元素:选择CustomerID为“BONAP”的单个客户Customercust=db.Customers.First(c=>c.CustomerID=="BONAP");条件:选择运费大于10.00的订单:Orderord=db.Orders.First(o=>o.Freight>10.00M);
Select/Distinct操作符适用场景:o(∩_∩)o…查询呗。适用场景说明:查询表达式中的select及所接子句是说明和SQL命令中的select作用相似但位置不同,放在表达式最后并把子句中的变量也就是结果返回回来;延迟。Select/Distinct操作包括9种形式,分别为简单用法、匿名类型形式、条件形式、指定类型形式、筛选形式、整形类型形式、嵌套类型形式、本地方法调用形式、Distinct形式。1.简单用法:1.简单用法:简单用法这个示例返回仅含客户联系人的序列。
2
varq=fromcindb.Customersselectc.ContactName;注意:这个语句只是一个声明或者一个描述,并没有真正把数据取出来,只有当你需要该数据的时候,它才会执行这个语句,这就是延迟加载(deferredloading)。如果,在声明的时候就返回的结果集是对象的集合。你可以使用ToList()或ToArray()方法把查询结果先进行保存,然后再对这个集合进行查询。当然延迟加载(deferredloading)可以像拼接SQL语句那样拼接查询语法,再执行它。2.匿名类型形式:2.匿名类型形式:匿名类型形式说明:匿名类型是C#3.0中新特性。其实质是编
译器根据我们自定义自动产生一个匿名的类来帮助我们实现临时变量的储存。匿名类型还依赖于另外一个特性:支持根据property来创建对象。比如,vard=new{Name="s"};编译器自动产生一个有property叫做Name的匿名类,然后按这个类型分配内存,并初始化对象。但是vard=new{"s"};是编译不通过的。因为,编译器不知道匿名类中的property的名字。例如stringc="d";vard=new{c};则是可以通过编译的。编译器会创建一个叫做匿名类带有叫c的property。例如下例:new{c,ContactName,c.Phone};ContactName和Phone都是在映射文件中定义与表中字段相对应的property。编译器读取数据并创建对象时,会创建一个匿名类,这个类有两个属性,为ContactName和Phone,然后根据数据初始化对象。另外编译器还可以重命名property的名字。varq=fromcindb.Customersselectnew{c.ContactName,c.Phone};上面语句描述:使用SELECT和匿名类型返回仅含客户联系人和电话号码的序列varq=fromeindb.Employeesselectnew{Name=e.FirstName+""+e.LastName,Phone=e.HomePhone};上面语句描述:使用SELECT和匿名类型返回仅含雇员和电话号码的序列,并将FirstName和LastName字段合并为一个字段“Name”,此外在所得的序列中将HomePhone字段重命名为Phone。
3
varq=frompindb.Productsselectnew{p.ProductID,HalfPrice=p.UnitPrice/2};上面语句描述:使用SELECT和匿名类型返回所有产品的ID以及HalfPrice(设置为产品单价除以2所得的值)的序列。
Count/Sum/Min/Max/Avg操作符适用场景:统计数据吧,比如统计一些数据的个数,求和,最小值,最大值,平均数。适用场景Count说明:返回集合中的元素个数,返回INT类型;不延迟。生成SQL语句为:SELECT说明COUNT(*)FROM1.简单形式:简单形式:简单形式得到数据库中客户的数量:varq=db.Customers.Count();2.带条件形式:带条件形式:带条件形式得到数据库中未断货产品的数量:varq=db.Products.Count(p=>!p.Discontinued);LongCount
4
说明:返回集合中的元素个数,返回LONG类型;不延迟。对于元素个数较多的集合可视说明情况可以选用LongCount来统计元素个数,它返回long类型,比较精确。生成SQL语句为:SELECTCOUNT_BIG(*)FROMvarq=db.Customers.LongCount();Sum说明:说明返回集合中数值类型元素之和,集合应为INT类型集合;不延迟。生成SQL语句为:SELECTSUM(…)FROM1.简单形式:简单形式:简单形式得到所有订单的总运费:varq=db.Orders.Select(o=>o.Freight).Sum();2.映射形式:映射形式:映射形式得到所有产品的订货总数:varq=db.Products.Sum(p=>p.UnitsOnOrder);Min
说明:返回集合中元素的最小值;不延迟。生成SQL语句为:SELECTMIN(…)FROM说明1.简单形式:1.简单形式:简单形式查找任意产品的最低单价:varq=db.Products.Select(p=>p.UnitPrice).Min();2.映射形式:2.映射形式:映射形式查找任意订单的最低运费:varq=db.Orders.Min(o=>o.Freight);3.元素:3.元素:元素查找每个类别中单价最低的产品:varcategories=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{
5
CategoryID=g.Key,CheapestProducts=fromp2ingwherep2.UnitPrice==g.Min(p3=>p3.UnitPrice)selectp2};
Max说明:返回集合中元素的最大值;不延迟。生成SQL语句为:SELECTMAX(…)FROM说明1.简单形式:1.简单形式:简单形式查找任意雇员的最近雇用日期:varq=db.Employees.Select(e=>e.HireDate).Max();2.映射形式:2.映射形式:映射形式查找任意产品的最大库存量:varq=db.Products.Max(p=>p.UnitsInStock);3.元素:3.元素:元素查找每个类别中单价最高的产品:varcategories=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,MostExpensiveProducts=fromp2ingwherep2.UnitPrice==g.Max(p3=>p3.UnitPrice)
6
selectp2};
Average说明:返回集合中的数值类型元素的平均值。集合应为数字类型集合,其返回值类型为说明double;不延迟。生成SQL语句为:SELECTAVG(…)FROM1.简单形式:1.简单形式:简单形式得到所有订单的平均运费:varq=db.Orders.Select(o=>o.Freight).Average();2.映射形式:2.映射形式:映射形式得到所有产品的平均单价:varq=db.Products.Average(p=>p.UnitPrice);3.元素:3.元素:元素查找每个类别中单价高于该类别平均单价的产品:varcategories=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,ExpensiveProducts=fromp2ingwherep2.UnitPrice>g.Average(p3=>p3.UnitPrice)selectp2};Aggregate
7
说明:根据输入的表达式获取聚合值;不延迟。即是说:用一个种子值与当前元素通过指定说明的函数来进行对比来遍历集合中的元素,符合条件的元素保留下来。如果没有指定种子值的话,种子值默认为集合的第一个元素。
Join操作符适用场景:在我们表关系中有一对一关系,一对多关系,多对多关系等。对各个表之间的关适用场景系,就用这些实现对多个表的操作。说明:在Join操作中,分别为Join(Join查询),SelectMany(Select一对多选择)和说明GroupJoin(分组Join查询)。该扩展方法对两个序列中键匹配的元素进行innerjoin操作SelectMany说明:我们在写查询语句时,如果被翻译成SelectMany需要满足2个条件。1:查询语句说明中没有join和into,必须出现EntitySet。2:在我们表关系
中有一对一关系,一对多关系,多对多关系等,下面分别介绍一下。1.一对多关系一对多关系(1toMany):一对多关系:varq=fromcindb.Customersfromoinc.Orderswherec.City=="London"selecto;语句描述:Customers与Orders是一对多关系。即Orders在Customers类中以EntitySet形式出现。所以第二个from是从c.Orders而不是db.Orders里进行筛选。这个例子在From子句中使用外键导航选择伦敦客户的所有订单。varq=frompindb.Productswherep.Supplier.Country=="USA"&;&;p.UnitsInStock==0selectp;语句描述:这一句使用了p.Supplier.Country条件,间接关联了Supplier表。这个例子在Where子句中使用外键导航筛选其供应商在美国且缺货的产品。生成SQL语句为:
8
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.Employeesfrometine.EmployeeTerritorieswheree.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]
9
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.Employeesfrome2ine1.Employeeswheree1.City==e2.Cityselectnew{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])Join操作符适用场景:在我们表关系中有一对一关系,一对多关系,多对多关系等。对各个表之间的关适用场景系,就用这些实现对多个表的操作。说明:在Join操作中,分别为Join(Join查询),SelectMany(Select一对多选择)和说明GroupJoin(分组Join查询)。该扩展方法对两个序列中键匹配的元素进行innerjoin操作
10
SelectMany说明:我们在写查询语句时,如果被翻译成SelectMany需要满足2个条件。1:查询语句中说明没有join和into,2:必须出现EntitySet。在我们表关系中有一对一关系,一对多关系,多对多关系等,下面分别介绍一下。1.一对多关系(1Many):1.一对多关系(1toMany):一对多关系varq=fromcindb.Customersfromoinc.Orderswherec.City=="London"selecto;语句描述:Customers与Orders是一对多关系。即Orders在Customers类中以EntitySet形式出现。所以第二个from是从c.Orders而不是db.Orders里进行筛选。这个例子在From子句中使用外键导航选择伦敦客户的所有订单。varq=frompindb.Productswherep.Supplier.Country=="USA"&;&;p.UnitsInStock==0selectp;语句描述:这一句使用了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]
11
2.多对多关系(ManyMany):2.多对多关系(ManytoMany):多对多关系varq=fromeindb.Employeesfrometine.EmployeeTerritorieswheree.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].[TerritoryI
D]WHERE([t0].[City]=@p0)AND([t1].[EmployeeID]=[t0].[EmployeeID])--@p0:InputNVarChar(Size=7;Prec=0;Scale=0)[Seattle]3.自联接关系:3.自联接关系:自联接关系varq=frome1indb.Employeesfrome2ine1.Employeeswheree1.City==e2.City
12
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.双向联接(Twojoin):1.双向联接(Twowayjoin):双向联接此示例显式联接两个表并从这两个表投影出结果:varq=fromcindb.Customersjoinoindb.Ordersonc.CustomerIDequalso.CustomerIDintoordersselectnew{c.ContactName,OrderCount=orders.Count()
13
};说明:在一对多关系中,左边是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.三向联接(Therejoin):2.三向联接(Therewayjoin):三向联接此示例显式联接三个表并分别从每个表投影出结果:varq=fromcindb.Customers
14
joinoindb.Ordersonc.CustomerIDequalso.CustomerIDintoordsjoineindb.Employeesonc.Cityequalse.Cityintoempsselectnew{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.左外部联接(LeftJoin):3.左外部联接(LeftOuterJoin):左外部联接此示例说明如何通过使用此示例说明如何通过使用DefaultIfEmpty()获取左外部联接。在雇员没有订单时,DefaultIfEmpty()方法返
回null:
15
varq=fromeindb.Employeesjoinoindb.Ordersoneequalso.Employeeintoordsfromoinords.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.投影的赋值(Projectedassignment):4.投影的Let赋值(Projectedletassignment):说明:let语句是重命名。let位于第一个from和select语句之间。这个例子从联接投影出最终“Let”表达式:varq=fromcindb.Customersjoinoindb.Ordersonc.CustomerIDequalso.CustomerIDintoordsletz=c.City+c.Countryfromoinordsselectnew{c.ContactName,
16
o.OrderID,z};
5.组合键(CompositeKey):5.组合键(CompositeKey):组合键这个例子显示带有组合键的联接:varq=fromoindb.Ordersfrompindb.Productsjoindindb.OrderDetailsonnew{o.OrderID,p.ProductID}equalsnew{d.OrderID,d.ProductID}intodetailsfromdindetailsselectnew{o.OrderID,
17
p.ProductID,d.UnitPrice};说明:使用三个表,并且用匿名类来说明:使用三个表,并且用匿名类来表示它们之间的关系。它们之间的关系不能用一个键描述清楚,所以用匿名类,来表示组合键。还有一种是两个表之间是用组合键表示关系的,不需要使用匿名类。6.可为null/不可为的键关系(Nullable/NonnullableRelationship):6.可为null/不可为null的键关系(Nullable/NonnullableKeyRelationship):这个实例显示如何构造一侧可为null而另一侧不可为null的联接:varq=fromoindb.Ordersjoineindb.Employeesono.EmployeeIDequals(int?)e.EmployeeIDintoempsfromeinempsselectnew{o.OrderID,e.FirstName};
OrderBy操作适用场景:对查询出的语句进行排序,比如按时间排序等等。适用场景说明:按指定表达式对集合排序;延迟,:按指定表达式对集合排序;延迟,默认是升序,说明加上descending表示降序,对应的扩展方法是OrderBy和OrderByDescending1.简单形式简单形式这个例子使用orderby按雇用日期对雇员进行排序:
18
varq=fromeindb.Employeesorderbye.HireDateselecte;说明:默认为升序2.带条件形式带条件形式注意:Where和OrderBy的顺序并不重要。而在T-SQL中,Where和OrderBy有严格的位置限制。varq=fromoindb.Orderswhereo.ShipCity=="London"orderbyo.Freightselecto;语句描述:使用where和
orderby按运费进行排序。3.降序排序降序排序varq=frompindb.Productsorderbyp.UnitPricedescendingselectp;4.ThenBy语句描述:使用复合的orderby对客户进行排序,进行排序:varq=fromcindb.Customersorderbyc.City,c.ContactNameselectc;
19
说明:按多个表达式进行排序,例如先按City排序,当City相同时,按ContactName排序。这一句用Lambda表达式像这样写:varq=.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操作适用场景:对查询出的语句进行排序,比如按时间排序等等。适用场景说明:按指定表达式对集合排序;延迟,:按指定表达式对集合排序;延迟,默认是升序,说明加上descending表示降序,对应的扩展方法是OrderBy和OrderByDescending1.简单形式1.简单形式这个例子使用orderby按雇用日期对雇员进行排序:varq=fromeindb.Employeesorderbye.HireDateselecte;说明:默认为升序
20
2.带条件形式2.带条件形式注意:Where和OrderBy的顺序并不重要。而在T-SQL中,Where和OrderBy有严格的位置限制。varq=fromoindb.Orderswhereo.ShipCity=="London"orderbyo.Freightselecto;语句描述:使用where和orderby按运费进行排序。3.降序排序3.降序排序varq=frompindb.Productsorderbyp.UnitPricedescendingselectp;4.ThenBy语句描述:使用复合的orderby对客户进行排序,进行排序:varq=fromcindb.Customersorderbyc.City,c.ContactNameselectc;说明:按多个表达式进行排序,例如先按City排序,City相同时,ContactName排序。当按这一句用Lambda表达式像这样写:varq=.OrderBy(c=>c.City).ThenBy(c=>c.ContactName).ToList();在T-SQL中没有ThenBy语句,其依然翻译为OrderBy,所以也可以用下面语句来表达:
21
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.Custom
ers.Select(c=>new{c.City,c.Address
22
}).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.Orderswhereo.EmployeeID==1orderbyo.ShipCountry,o.Freightdescendingselecto;语句描述:使用orderby先按发往国家再按运费从高到低的顺序对EmployeeID1的订单进行排序。6.带6.带GroupBy形式varq=frompindb.Productsgrouppbyp.CategoryIDintogorderbyg.Keyselectnew{g.Key,MostExpensiveProducts=
23
fromp2ingwherep2.UnitPrice==g.Max(p3=>p3.UnitPrice)selectp2};语句描述:使用orderby、Max和GroupBy得出每种类别中单价最高的产品,并按CategoryID对这组产品进行排序。
GroupBy/Having操作符适用场景:分组数据,为我们查找数据缩小范围。适用场景说明:分配并返回对传入参数进行分组操作后的可枚举对象。分组;延迟说明1.简单形式:简单形式:简单形式varq=frompindb.Productsgrouppbyp.CategoryIDintogselectg;语句描述:使用GroupBy按CategoryID划分产品。说明:frompindb.Products表示从表中将产品对象取出来。grouppbyp.CategoryIDintog表示对p按CategoryID字段归类。其结果命名为g,一旦重新命名,p的作用域就结束了,所以,最后select时,只能selectg。当然,也不必重新命名可以这样写:varq=frompindb.Productsgrouppbyp.CategoryID;我们用示意图表示:
24
如果想遍历某类别中所有记录,这样:foreach(vargpinq){if(gp.Key==2){foreach(varitemingp){//dosomething}}}2.Select匿名类:匿名类:varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{CategoryID=g.Key,g};
25
说明:在这句LINQ语句中,有2个property:CategoryID和g。这个匿名类,其实质是对返回结果集重新进行了包装。把g的property封装成一个完整的分组。如下图所示:
如果想遍历某匿名类中所有记录,要这么做:foreach(vargpinq){if(gp.CategoryID==2){foreach(varitemingp.g){//dosomething}}}GroupBy/Having操作符适用场景:分组数据,为我们查找数据缩小范围。适用场景说明:分配并返回对传入参数进行分组操作后的可枚举对象。分组;延迟说明1.简单形式:1.简单形式:简单形式
26
varq=frompindb.Productsgrouppbyp.CategoryIDintogselectg;语句描述:使用Grou
pBy按CategoryID划分产品。说明:frompindb.Products表示从表中将产品对象取出来。grouppbyp.CategoryIDintog表示对p按CategoryID字段归类。其结果命名为g,一旦重新命名,的作用域就结束了,p所以,最后select时,只能selectg。当然,也不必重新命名可以这样写:varq=frompindb.Productsgrouppbyp.CategoryID;我们用示意图表示:
如果想遍历某类别中所有记录,这样:foreach(vargpinq){if(gp.Key==2){
27
foreach(varitemingp){//dosomething}}}匿名类:2.Select匿名类:varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{CategoryID=g.Key,g};说明:在这句LINQ语句中,有2个property:CategoryID和g。这个匿名类,其实质是对返回结果集重新进行了包装。把g的property封装成一个完整的分组。如下图所示:
如果想遍历某匿名类中所有记录,要这么做:foreach(vargpinq){if(gp.CategoryID==2)
28
{foreach(varitemingp.g){//dosomething}}}
3.最大值3.最大值varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,MaxPrice=g.Max(p=>p.UnitPrice)};语句描述:使用GroupBy和Max查找每个CategoryID的最高单价。说明:先按CategoryID归类,判断各个分类产品中单价最大的Products。取出CategoryID值,并把UnitPrice值赋给MaxPrice。4.最小值4.最小值varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,MinPrice=g.Min(p=>p.UnitPrice)
29
};语句描述:使用GroupBy和Min查找每个CategoryID的最低单价。说明:先按CategoryID归类,判断各个分类产品中单价最小的Products。取出CategoryID值,并把UnitPrice值赋给MinPrice。5.平均值5.平均值varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,AveragePrice=g.Average(p=>p.UnitPrice)};语句描述:使用GroupBy和Average得到每个CategoryID的平均单价。说明:先按CategoryID归类,取出CategoryID值和各个分类产品中单价的平均值。6.求和6.求和varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,TotalPrice=g.Sum(p=>p.UnitPrice)};语句描述:使用GroupBy和Sum得到每个CategoryID的单价总计。说明:先按CategoryID归类,取出CategoryID值和各个分类产品中单价的总和。
7.计数7.计数
30
varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,NumProducts=g.Count()};语句描述:使用GroupBy和Count得到每个CategoryID中产品的数量。说明:先按CategoryID归类,取出CategoryID值和各个分类产品的数量。8.带条件计数8.带条件计数varq=frompindb.Productsgrouppbyp.CategoryIDintogselectnew{g.Key,NumProducts=g.Count(p=>p.Discontinue
d)};语句描述:使用GroupBy和Count得到每个CategoryID中断货产品的数量。说明:先按CategoryID归类,取出CategoryID值和各个分类产品的断货数量。Count函数里,使用了Lambda表达式,Lambda表达式中的p,代表这个组里的一个元素或对象,即某一个产品。9.Where限制varq=frompindb.Productsgrouppbyp.CategoryIDintogwhereg.Count()>=10
31
selectnew{g.Key,ProductCount=g.Count()};语句描述:根据产品的―ID分组,查询产品数量大于10的ID和产品数量。这个示例在GroupBy子句后使用Where子句查找所有至少有10种产品的类别。说明:在翻译成SQL语句时,在最外层嵌套了Where条件。10.多列(Multiple10.多列(MultipleColumns)多列varcategories=frompindb.Productsgrouppbynew{p.CategoryID,p.SupplierID}intogselectnew{g.Key,g};语句描述:使用GroupBy按CategoryID和SupplierID将产品分组。说明:既按产品的分类,又按供应商分类。在by后面,new出来一个匿名类。这里,Key其实质是一个类的对象,Key包含两个Property:CategoryID、SupplierID。用g.Key.CategoryID可以遍历CategoryID的值。11.表达式(Expression)11.表达式(Expression)表达式varcategories=
32
frompindb.Productsgrouppbynew{Criterion=p.UnitPrice>10}intogselectg;语句描述:使用GroupBy返回两个产品序列。第一个序列包含单价大于10的产品。第二个序列包含单价小于或等于10的产品。说明:按产品单价是否大于10分类。其结果分为两类,大于的是一类,小于及等于为另一类。
Exists/In/Any/All/Contains操作符适用场景:用于判断集合中元素,进一步缩小范围。适用场景Any说明:用于判断集合中是否有元素满足某一条件;不延迟。(若条件为空,则集合只要不为空就返回True,否则为False)。有2种形式,分别为简单形式和带条件形式。1.简单形式:简单形式:简单形式仅返回没有订单的客户:varq=fromcindb.Customerswhere!c.Orders.Any()selectc;生成SQL语句为:SELECT[t0].[CustomerID],[t0].[CompanyName],[t0].[ContactName],[t0].[ContactTitle],[t0].[Address],[t0].[City],[t0].[Region],[t0].[PostalCode],[t0].[Country],[t0].[Phone],[t0].[Fax]FROM[dbo].[Customers]AS[t0]WHERENOT(EXISTS(SELECTNULLAS[EMPTY]FROM[dbo].[Orders]AS[t1]
33
WHERE[t1].[CustomerID]=[t0].[CustomerID]))2.带条件形式:带条件形式:带条件形式仅返回至少有一种产品断货的类别:varq=fromcindb.Categorieswherec.Products.Any(p=>p.Discontinued)selectc;生成SQL语句为:SELECT[t0].[CategoryID],[t0].[CategoryName],[t0].[Description],[t0].[Picture]FROM[dbo].[Categories]AS[t0]WHEREEXISTS(SELECTNULLAS[EMPTY]FROM[dbo].[Products]AS[t1]WHERE([t
1].[Discontinued]=1)AND([t1].[CategoryID]=[t0].[CategoryID]))Exists/In/Any/All/Contains操作符适用场景:用于判断集合中元素,进一步缩小范围。适用场景Any说明:用于判断集合中是否有元素满足某一条件;不延迟。(若条件为空,则集合只要不为空就返回True,否则为False)。有2种形式,分别为简单形式和带条件形式。1.简单形式:1.简单形式:简单形式仅返回没有订单的客户:varq=fromcindb.Customerswhere!c.Orders.Any()
34
selectc;生成SQL语句为:SELECT[t0].[CustomerID],[t0].[CompanyName],[t0].[ContactName],[t0].[ContactTitle],[t0].[Address],[t0].[City],[t0].[Region],[t0].[PostalCode],[t0].[Country],[t0].[Phone],[t0].[Fax]FROM[dbo].[Customers]AS[t0]WHERENOT(EXISTS(SELECTNULLAS[EMPTY]FROM[dbo].[Orders]AS[t1]WHERE[t1].[CustomerID]=[t0].[CustomerID]))2.带条件形式:2.带条件形式:带条件形式仅返回至少有一种产品断货的类别:varq=fromcindb.Categorieswherec.Products.Any(p=>p.Discontinued)selectc;生成SQL语句为:SELECT[t0].[CategoryID],[t0].[CategoryName],[t0].[Description],[t0].[Picture]FROM[dbo].[Categories]AS[t0]WHEREEXISTS(SELECTNULLAS[EMPTY]FROM[dbo].[Products]AS[t1]WHERE([t1].[Discontinued]=1)AND([t1].[CategoryID]=[t0].[CategoryID]))
35
All说明:用于判断集合中所有元素是否都满足某一条件;不延迟1.带条件形式1.带条件形式varq=fromcindb.Customerswherec.Orders.All(o=>o.ShipCity==c.City)selectc;语句描述:这个例子返回所有订单都运往其所在城市的客户或未下订单的客户。Contains说明:用于判断集合中是否包含有某一元素;不延迟。它是对两个序列进行连接操作的。string[]customerID_Set=newstring[]{"AROUT","BOLID","FISSA"};varq=(fromoindb.OrderswherecustomerID_Set.Contains(o.CustomerID)selecto).ToList();语句描述:查找"AROUT","BOLID"和"FISSA"这三个客户的订单。先定义了一个数组,在LINQtoSQL中使用Contains,数组中包含了所有的CustomerID,即返回结果中,所有的CustomerID都在这个集合内。也就是in。你也可以把数组的定义放在LINQtoSQL语句里。比如:varq=(fromoindb.Orderswhere(newstring[]{"AROUT","BOLID","FISSA"}).Contains(o.CustomerID)selecto).ToList();
36
NotContains则取反:varq=(fromoindb.Orderswhere!(newstring[]{"AROUT","BOLID","FISSA"}).Contains(o.CustomerID)selecto).ToList();1.包含一个对象:1.包含一个对象:包含一个对象varorder=(fromoindb.Orderswhereo.OrderID==10248selecto).First();varq=db.Customers.Where(p=>p.Orders.Contains(order)).ToList();foreach(varcustinq){foreach(varordincust.Orders){//dosomething}}语句描述:这个例子使用Contain查找哪个客户包含Orde
rID为10248的订单。2.包含多个值:2.包含多个值:包含多个值string[]cities=newstring[]{"Seattle","London","Vancouver","Paris"};varq=db.Customers.Where(p=>cities.Contains(p.City)).ToList();语句描述:这个例子使用Contains查找其所在城市为西雅图、伦敦、巴黎或温哥华的客户。
37
Concat/Union/Intersect/Except操作适用场景:对两个集合的处理,例如追加、合并、取相同项、相交项等等。Concat(连接)(连接)说明:连接不同的集合,不会自动过滤相同项;延迟。1.简单形式:简单形式:简单形式varq=(fromcindb.Customersselectc.Phone).Concat(fromcindb.Customersselectc.Fax).Concat(fromeindb.Employeesselecte.HomePhone);语句描述:返回所有消费者和雇员的电话和传真。2.复合形式:复合形式:复合形式varq=(fromcindb.Customersselectnew
38
{Name=c.CompanyName,c.Phone}).Concat(fromeindb.Employeesselectnew{Name=e.FirstName+""+e.LastName,Phone=e.HomePhone});语句描述:返回所有消费者和雇员的和电话。Union(合并)(合并)说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。varq=(fromcindb.Customersselectc.Country).Union(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员所在的国家。Intersect(相交)(相交)
39
说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素,然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。varq=(fromcindb.Customersselectc.Country).Intersect(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员同在的国家。Except(与非)(与非)说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合,返回第二个集合中所有未出现在前面所得元素集合中的元素。varq=(fromcindb.Customersselectc.Country).Except(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员不同的国家。Concat/Union/Intersect/Except操作适用场景:对两个集合的处理,例如追加、合并、取相同项、相交项等等。Concat(连接)(连接)说明:连接不同的集合,不会自动过滤相同项;延迟。
40
1.简单形式:简单形式:简单形式varq=(fromcindb.Customersselectc.Phone).Concat(fromcindb.Customersselectc.Fax).Concat(fromeindb.Employeesselecte.HomePhone);语句描述:返回所有消费者和雇员的电话和传真。2.复合形式:复合形式:复合形式varq=
(fromcindb.Customersselectnew{Name=c.CompanyName,c.Phone}).Concat(fromeindb.Employeesselectnew{Name=e.FirstName+""+e.LastName,
41
Phone=e.HomePhone});语句描述:返回所有消费者和雇员的和电话。Union(合并)(合并)说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。varq=(fromcindb.Customersselectc.Country).Union(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员所在的国家。Intersect(相交)(相交)说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素,然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。varq=(fromcindb.Customersselectc.Country).Intersect(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员同在的国家。
42
Except(与非)(与非)说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合,返回第二个集合中所有未出现在前面所得元素集合中的元素。varq=(fromcindb.Customersselectc.Country).Except(fromeindb.Employeesselecte.Country);语句描述:查询顾客和职员不同的国家。);语句描述:查询顾客和职员不同的国家。
43