Select/Distinct *** 作包括9种形式,分别为简单用法、匿名类型形式、条件形式、指定类型形式、筛选形式、整形类型形式、嵌套类型形式、本地方法调用形式、Distinct形式。
1.简单用法:
这个示例返回仅含客户联系人姓名的序列。
var q =
from c in db.Customers
select c.ContactName
注意:这个语句只是一个声明或者一个描述,并没有真正把数据取出来,只有当你需要该数据的时候,它才会执行这个语句,这就是延迟加载(deferred loading)。如果,在声明的时候就返回的结果集是对象的集合。你可以使用ToList() 或ToArray()方法把查询结果先进行保存,然后再对这个集合进行查询。当然延迟加载(deferred loading)可以像拼接SQL语句那样拼接查询语法,再执行它。
2.匿名类型形式:
说明:匿名类型是C#3.0中新特性。其实质是编译器根据我们自定义自动产生一个匿名的类来帮助我们实现临时变量的储存。匿名类型还依赖于另外一个特性:支持根据property来创建对象。比如,var d = new { Name = "s" }编译器自动产生一个有property叫做Name的匿名类,然后按这个类型分配内存,并初始化对象。但是var d = new {"s"}是编译不通过的。因为,编译器不知道匿名类中的property的名字。例如string c = "d"var d = new { c}则是可以通过编译的。编译器会创建一个叫做匿名类带有叫c的property。
例如下例:new{c,ContactName,c.Phone}ContactName和Phone都是在映射文件中定义与表中字段相对应的property。编译器读取数据并创建对象时,会创建一个匿名类,这个类有两个属性,为ContactName和Phone,然后根据数据初始化对象。另外编译器还可以重命名property的名字。
var q =
from c in db.Customers
select new {c.ContactName, c.Phone}
上面语句描述:使用 SELECT 和匿名类型返回仅含客户联系人姓名和电话号码的序列
var q =
from e in db.Employees
select new
{
Name = e.FirstName + " " + e.LastName,
Phone = e.HomePhone
}
上面语句描述:使用SELECT和匿名类型返回仅含雇员姓名和电话号码的序列,并将FirstName和LastName字段合并为一个字段“Name”,此外在所得的序列中将HomePhone字段重命名为Phone。
var q =
from p in db.Products
select new
{
p.ProductID,
HalfPrice = p.UnitPrice / 2
}
上面语句描述:使用SELECT和匿名类型返回所有产品的ID以及HalfPrice(设置为产品单价除以2所得的值)的序列。
3.条件形式:
说明:生成SQL语句为:case when condition then else。
var q =
from p in db.Products
select new
{
p.ProductName,
Availability =
p.UnitsInStock - p.UnitsOnOrder <0 ?
"Out Of Stock" : "In Stock"
}
上面语句描述:使用SELECT和条件语句返回产品名称和产品供货状态的序列。
4.指定类型形式:
说明:该形式返回你自定义类型的对象集。
var q =
from e in db.Employees
select new Name
{
FirstName = e.FirstName,
LastName = e.LastName
}
上面语句描述:使用SELECT和已知类型返回雇员姓名的序列。
5.筛选形式:
说明:结合where使用,起到过滤作用。
var q =
from c in db.Customers
where c.City == "London"
select c.ContactName
上面语句描述:使用SELECT和WHERE返回仅含伦敦客户联系人姓名的序列。
6.shaped形式(整形类型):
说明:其select *** 作使用了匿名对象,而这个匿名对象中,其属性也是个匿名对象。
var q =
from c in db.Customers
select new {
c.CustomerID,
CompanyInfo = new {c.CompanyName, c.City, c.Country},
ContactInfo = new {c.ContactName, c.ContactTitle}
}
语句描述:使用SELECT 和匿名类型返回有关客户的数据的整形子集。查询顾客的ID和公司信息(公司名称,城市,国家)以及联系信息(联系人和职位)。
7.嵌套类型形式:
说明:返回的对象集中的每个对象DiscountedProducts属性中,又包含一个集合。也就是每个对象也是一个集合类。
var q =
from o in db.Orders
select new {
o.OrderID,
DiscountedProducts =
from od in o.OrderDetails
where od.Discount >0.0
select od,
FreeShippingDiscount = o.Freight
}
语句描述:使用嵌套查询返回所有订单及其OrderID 的序列、打折订单中项目的子序列以及免送货所省下的金额。
8.本地方法调用形式(LocalMethodCall):
这个例子在查询中调用本地方法PhoneNumberConverter将电话号码转换为国际格式。
var q = from c in db.Customers
where c.Country == "UK" || c.Country == "USA"
select new
{
c.CustomerID,
c.CompanyName,
Phone = c.Phone,
InternationalPhone =
PhoneNumberConverter(c.Country, c.Phone)
}
PhoneNumberConverter方法如下:
public string PhoneNumberConverter(string Country, string Phone)
{
Phone = Phone.Replace(" ", "").Replace(")", ")-")
switch (Country)
{
case "USA":
return "1-" + Phone
case "UK":
return "44-" + Phone
default:
return Phone
}
}
下面也是使用了这个方法将电话号码转换为国际格式并创建XDocument
XDocument doc = new XDocument(
new XElement("Customers", from c in db.Customers
where c.Country == "UK" || c.Country == "USA"
select (new XElement("Customer",
new XAttribute("CustomerID", c.CustomerID),
new XAttribute("CompanyName", c.CompanyName),
new XAttribute("InterationalPhone",
PhoneNumberConverter(c.Country, c.Phone))
))))
9.Distinct形式:
说明:筛选字段中不相同的值。用于查询不重复的结果集。生成SQL语句为:SELECT DISTINCT [City] FROM [Customers]
var q = (
from c in db.Customers
select c.City )
.Distinct()
语句描述:查询顾客覆盖的国家。
Count/Sum/Min/Max/Avg *** 作符
适用场景:统计数据吧,比如统计一些数据的个数,求和,最小值,最大值,平均数。
Count
说明:返回集合中的元素个数,返回INT类型;不延迟。生成SQL语句为:SELECT COUNT(*) FROM
1.简单形式:
得到数据库中客户的数量:
var q = db.Customers.Count()
2.带条件形式:
得到数据库中未断货产品的数量:
var q = db.Products.Count(p =>!p.Discontinued)
LongCount
说明:返回集合中的元素个数,返回LONG类型;不延迟。对于元素个数较多的集合可视情况可以选用LongCount来统计元素个数,它返回long类型,比较精确。生成SQL语句为:SELECT COUNT_BIG(*) FROM
var q = db.Customers.LongCount()
Sum
说明:返回集合中数值类型元素之和,集合应为INT类型集合;不延迟。生成SQL语句为:SELECT SUM(…) FROM
1.简单形式:
得到所有订单的总运费:
var q = db.Orders.Select(o =>o.Freight).Sum()
2.映射形式:
得到所有产品的订货总数:
var q = db.Products.Sum(p =>p.UnitsOnOrder)
Min
说明:返回集合中元素的最小值;不延迟。生成SQL语句为:SELECT MIN(…) FROM
1.简单形式:
查找任意产品的最低单价:
var q = db.Products.Select(p =>p.UnitPrice).Min()
2.映射形式:
查找任意订单的最低运费:
var q = db.Orders.Min(o =>o.Freight)
3.元素:
查找每个类别中单价最低的产品:
var categories =
from p in db.Products
group p by p.CategoryID into g
select new {
CategoryID = g.Key,
CheapestProducts =
from p2 in g
where p2.UnitPrice == g.Min(p3 =>p3.UnitPrice)
select p2
}
Max
说明:返回集合中元素的最大值;不延迟。生成SQL语句为:SELECT MAX(…) FROM
1.简单形式:
查找任意雇员的最近雇用日期:
var q = db.Employees.Select(e =>e.HireDate).Max()
2.映射形式:
查找任意产品的最大库存量:
var q = db.Products.Max(p =>p.UnitsInStock)
3.元素:
查找每个类别中单价最高的产品:
var categories =
from p in db.Products
group p by p.CategoryID into g
select new {
g.Key,
MostExpensiveProducts =
from p2 in g
where p2.UnitPrice == g.Max(p3 =>p3.UnitPrice)
select p2
}
Average
说明:返回集合中的数值类型元素的平均值。集合应为数字类型集合,其返回值类型为double;不延迟。生成SQL语句为:SELECT AVG(…) FROM
1.简单形式:
得到所有订单的平均运费:
var q = db.Orders.Select(o =>o.Freight).Average()
2.映射形式:
得到所有产品的平均单价:
var q = db.Products.Average(p =>p.UnitPrice)
3.元素:
查找每个类别中单价高于该类别平均单价的产品:
var categories =
from p in db.Products
group p by p.CategoryID into g
select new {
g.Key,
ExpensiveProducts =
from p2 in g
where p2.UnitPrice >g.Average(p3 =>p3.UnitPrice)
select p2
}
Aggregate
说明:根据输入的表达式获取聚合值;不延迟。即是说:用一个种子值与当前元素通过指定的函数来进行对比来遍历集合中的元素,符合条件的元素保留下来。如果没有指定种子值的话,种子值默认为集合的第一个元素。
LINQ to SQL语句的关键字一览
Where 过滤;延迟
Select 选择;延迟
Distinct 查询不重复的结果集;延迟
Count 返回集合中的元素个数,返回INT类型;不延迟
LongCount 返回集合中的元素个数,返回LONG类型;不延迟
Sum 返回集合中数值类型元素之和,集合应为INT类型集合;不延迟
Min 返回集合中元素的最小值;不延迟
Max 返回集合中元素的最大值;不延迟
Average 返回集合中的数值类型元素的平均值。集合应为数字类型集合,其返回值类型为double;不延迟
Aggregate 根据输入的表达式获取聚合值;不延迟
参考我提供的链接 匿名对象就是需要声明一个名字的对象 就是调用构造函数。临时对象一般是系统自动生成的 比如你的函数返回一个对象,这个对象在返回时会生成一个临时对象
你调用函数时候,传入的一个表达式,这个表达式会算出一个临时变量
最简单的 2+3+6 会被编译器编译成
x=2+3
y=x+6
这里编译器生成了两个临时对象 虽然都是int型的
一、什么是属性描述符?
MDN:
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。
数据描述符是一个拥有可写或不可写值的属性。
存取描述符是由一对 getter-setter 函数功能来描述的属性。
描述符必须是两种形式之一;不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
value 与属性相关的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable true 当且仅当可能用赋值运算符改变与属性相关的值。默认为 false。
存取描述符同时具有以下可选键值:
get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。方法将返回用作属性的值。默认为 undefined。 set 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将收到作为唯一参数的新值分配给属性。默认为 undefined。
以上是摘自MDN的解释,看起来是很晦涩的,具体什么意思呢: 首先我们从以上解释知道该匿名参数对象有个很好听的名字叫属性描述符,属性描述符又分成两大块:数据描述符以及存取描述符(其实只是一个外号,给指定的属性集合起个外号)。
数据描述符包括两个属性 :value属性以及writable属性,第一个属性用来声明当前欲修饰的属性的值,第二个属性用来声明当前对象是否可写即是否可以修改
存取描述符就包括get与set属性用来声明欲修饰的象属性的getter及setter
属性描述符内部,数据描述符与存取描述符只能存在其中之一,但是不论使用哪个描述符都可以同时设置configurable属性以及enumerable属性。
configurable属性用来声明欲修饰的属性是否能够配置,仅有当其值为true时,被修饰的属性才有可能能够被删除,或者重新配置。
enumerable属性用来声明欲修饰属性是否可以被枚举。
知道了什么是属性描述符,我们就可以开始着手创建一些对象并开始配置其属性
顺便给大家推荐一个裙,它的前面是 537,中间是631,最后就是 707。想要学习前端的小伙伴可以加入我们一起学习,互相帮助。群里每天晚上都有大神免费直播上课,如果不是想学习的小伙伴就不要加啦。
二、创建属性不可配置不可枚举的对象
//使用默认值配置
(function(){
varobj = {}//声明一个空对象
Object.defineProperty(obj,"key",{
value:"static"
//没有设置 enumerable 使用默认值 false
//没有 configurable 使用默认值 false
//没有 writable 使用默认值 false
})
console.log(obj.key)//输出 “static”
obj.key ="new"//尝试修改其值,修改将失败,因为 writable 为 false
console.log(obj.key)//输出 “static”
obj.a =1//动态添加一个属性
for(variteminobj){//遍历所有 obj 的可枚举属性
console.log(item)
}//只输出一个 “a” 因为 “key”的 enumerable为 false
})()
//显示配置 等价于上面
(function(){
varobj = {}
Object.defineProperty(obj,"key",{
enumerable:false,
configurable:false,
writable:false,
value:"static"
})
})()
//等价配置
(function(){
varo = {}
o.a =1
//等价于
Object.defineProperty(o,"a",{value:1,
writable:true,
configurable:true,
enumerable:true})
Object.defineProperty(o,"a",{value:1})
//等价于
Object.defineProperty(o,"a",{value:1,
writable:false,
configurable:false,
enumerable:false})
})()
三、Enumerable 特性
属性特性enumerable决定属性是否能被for...in循环或Object.keys方法遍历得到
(function(){
varo = {}
Object.defineProperty(o,"a",{value:1,enumerable:true})
Object.defineProperty(o,"b",{value:2,enumerable:false})
Object.defineProperty(o,"c",{value:2})//enumerable default to false
o.d =4//如果直接赋值的方式创建对象的属性,则这个属性的 enumerable 为 true
for(varitemino){//遍历所有可枚举属性包括继承的属性
console.log(item)
}
console.log(Object.keys(o))//获取 o 对象的所有可遍历属性不包括继承的属性
console.log(o.propertyIsEnumerable('a'))//true
console.log(o.propertyIsEnumerable('b'))//false
console.log(o.propertyIsEnumerable('c'))//false
})()
输出结果如下:
四、Configurable 特性
(function(){
varo = {}
Object.defineProperty(o,"a",{get:function(){return1},
configurable:false} )
//enumerable 默认为 false,
//value 默认为 undefined,
//writable 默认为 false,
//set 默认为 undefined
//抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置
Object.defineProperty(o,"a",{configurable:true} )
//抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置,enumerable 的原值为 false
Object.defineProperty(o,"a",{enumerable:true} )
//抛出异常,因为最开始定义了 configurable 为 false,set的原值为 undefined
Object.defineProperty(o,"a",{set:function(val){}} )
//抛出异常,因为最开始定义了 configurable 为 false,故无法进行覆盖,尽管想用一样的来覆盖
Object.defineProperty(o,"a",{get:function(){return1}})
//抛出异常,因为最开始定义了 configurable 为 false,故无法将其进行重新配置把属性描述符从存取描述符改为数据描述符
Object.defineProperty(o,"a",{value:12})
console.log(o.a)//输出1
deleteo.a//想要删除属性,将失败
console.log(o.a)//输出1
})()
五、提高及扩展
1.属性描述符中容易被误导的地方之writable与configurable
(function(){
varo = {}
Object.defineProperties(o,{
"a": {
value:1,
writable:true,//可写
configurable:false//不可配置
//enumerable 默认为 false 不可枚举
},
"b":{
get:function(){
returnthis.a
},
configurable:false
}
})
console.log(o.a)//1
o.a =2//修改值成功,writable 为 true
console.log(o.a)//2
Object.defineProperty(o,"a",{value:3})//同样为修改值成功
console.log(o.a)//3
//将其属性 b 的属性描述符从存取描述符重新配置为数据描述符
Object.defineProperty(o,"b",{value:3})//抛出异常,因为 configurable 为 false
})()
2.通过上面的学习,我们都知道传递属性描述符参数时,是定义一个匿名的对象,里面包含属性描述符内容,若每定义一次便要创建一个匿名对象传入,将会造成内存浪费。故优化如下:
(function(){
varobj = {}
//回收同一对象,即减少内存浪费
functionwithValue(value){
vard = withValue.d ||(
withValue.d = {
enumerable:false,
configurable:false,
writable:false,
value:null
}
)
d.value = value
returnd
}
Object.defineProperty(obj,"key",withValue("static"))
})()
最后给大家推荐一个裙,它的前面是 537,中间是631,最后就是 707。想要学习前端的小伙伴可以加入我们一起学习,互相帮助。群里每天晚上都有大神免费直播上课,如果不是想学习的小伙伴就不要加啦。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)