LINQ(集成化查询)

时间:2022-12-25 20:19:10

LINQ可以对数组、集合等数据结构进行查询、筛选、排序等操作;也可以用于与数据库交互;也支持对XML的操作,使用LINQ技术可以动态创建、筛选和修改XML数据和直接操作XML文件。

一). LINQ基本语法:

(1)所有的LINQ查询表达式都是以from....in....开头;

(2)以select或group子句结束。以select子句结束表示从数据源序列筛选出元素;以group子句结束表示将从数据源序列中筛选出来的元素进行分组,并把每个分组放进查询结果集中。

例如:var result=from str in list select str;

var result from str in list group s by str[0];

二).延迟执行与强制立即执行

先看以下代码:var result=from str in list select str;当执行上述代码时,LINQ查询实际上并未执行,而是仅仅把用于查询的“命令”存放在result变量中,只到执行到遍历访问代码时才会执行查询:foreach(var a in result){。。。。。},这就是延迟执行。当然,可以调用Count,ToList,ToArray等方法来时查询立即执行,即使LINQ查询强行立即执行。

三).筛选、排序、分组

(1)在查询语句中,用where子句来设定筛选条件(一个或多个条件),如果where子句后面条件为真,则符合条件;若为假,则不符合条件。

例如:var a=from b in c where b>10 select b;

(2)对查询结果重新排序可以用orderby子句,默认情况下按升序排序,如果要进行降序排序,就必须在orderby子句后加上descending关键字。

例如:var a=from b in c orderby b select b;

(3)对数据进行分组要有分组依据,因此group一般与by关键字连用,格式如下:group <要进行分组的元素>by<分组依据>

如果要对分组的数据进行操作,可以在查询语句中储存个分组的数据,即在分组语句后面接上into关键字。如:group emp by emp.Department into eg;数据分组后会将每个分量都存入eg变量中,随后可以用select子句把存放在eg中的分组选择进行结果中。如下:group emp by emp.Department into eg select eg;这时候查询结果中的每个元素都是IGrouping<TKey,TElement>类型的对象,IGrouping<TKey,TElement>带了2个类型参数,TKey表示分组依据(Key)的类型,TElement表示每个分组中元素的类型,由于IGrouping接口继承自IEnumerable<out T>接口,因此,只要使用foreach循环就可以访问分组中的元素。

            // 示例数据源
string[] arr = { "table", "use", "up", "take", "turn", "reset", "remove", "we", "wave", "work", "word" }; // 查询数据源中的所有元素
// 并以首字母作为分组依据
var res = from s in arr
group s by s.ToUpper()[];
// 输出查询结果
Console.WriteLine("共有{0}个分组。", res.Count());
foreach (IGrouping<char, string> item in res)
{
Console.WriteLine("--------- {0} --------", item.Key);
// 取出该分组中的元素
foreach (string str in item)
{
Console.WriteLine(" {0}", str);
}
Console.WriteLine();
}

下面在看一例:

public class Student
{
/// <summary>
/// 学员ID
/// </summary>
public uint StuID { get; set; }
/// <summary>
/// 学员姓名
/// </summary>
public string StuName { get; set; }
/// <summary>
/// 课程
/// </summary>
public string Course { get; set; }
}
            Student[] students =
{
new Student { StuID = , StuName = "小陈", Course = "C++基础" },
new Student { StuID = , StuName = "小林", Course = "VB入门" },
new Student { StuID = , StuName = "小邓", Course = "C++基础" },
new Student { StuID = , StuName = "小李", Course = "C#客户端开发" },
new Student { StuID = , StuName = "小唐", Course = "C++基础" },
new Student { StuID = , StuName = "小周", Course = "VB入门" },
new Student { StuID = , StuName = "小张", Course = "VB入门" },
new Student { StuID = , StuName = "小吴", Course = "C#客户端开发" },
new Student { StuID = , StuName = "小孙", Course = "C++基础" },
new Student { StuID = , StuName = "小孟", Course = "C#客户端开发" }
};
// 筛选出学号大于5的学员
// 并按课程进行分组
// 学号按降序排列
var res = from s in students
orderby s.StuID descending
where s.StuID >
group s by s.Course into g
select g;
foreach (var g in res)
{
Console.WriteLine("----- {0} -----", g.Key);
foreach (Student stu in g)
{
Console.WriteLine("学号:{0},姓名:{1},课程:{2}", stu.StuID, stu.StuName, stu.Course);
}
Console.WriteLine();
}

四).复杂查询

(1)动态创建类型

在比较复杂的查询中,查询结果通常会生成一个新的类型,以使其内部包含来自多个数据序列的属性。许多时候,这些新类型并不是固定的,不同的查询需求会产生不同的结果,如果为每种查询结果都去定义相应的类,那有可能变得很复杂,面对这种情况,使用动态类型是较理想的选择。动态类型无需事先去定义类,即可根据代码上下文的需要动态地去创建新类型,实现方法是运用new运算符,创建的新类型并没有确切的名称,是由编译器自动分配的,因此在声明量时应使用var关键字,由编译器自动去识别其类型。

例如:

            var a = new
{
b = "cajj",
c =
};
Console.WriteLine("{0} {1}", a.b, a.c);

也可以使用dynamic关键字来声明用于引用匿名类型的变量。使用dynamic声明的变量属于动态类型,在编译阶段不进行解析,只在运行时动态解析。

例如:

dynamic b = new
{
Name = "Java",
Age = ,
Birth = new DateTime(, , )
};
Console.WriteLine("Name={0} Age={1} Birth={2:yyyy-M-d}", b.Name, b.Age, b.Birth);

(2)联合查询

联合查询主要通过jion关键字来完成的。所谓的联合查询,可以理解为联合多个数据序列进行查询,并从中返回查询结果。查询结果中的数据可能来自于多个数据序列。多个数据序列要进行联合,需要提供一个联合条件才能使多个序列完成正确的联合,所以,jion关键字后面紧跟着on关键字,并通过equals关键字来判断联合条件是否成立。

代码如下:

    /// <summary>
/// 图书分类信息
/// </summary>
public class Category
{
/// <summary>
/// 分别ID
/// </summary>
public int catID { get; set; }
/// <summary>
/// 分类名
/// </summary>
public string catName { get; set; }
} /// <summary>
/// 图书信息
/// </summary>
public class BookInfo
{
/// <summary>
/// 图书ID
/// </summary>
public int BookID { get; set; }
/// <summary>
/// 书名
/// </summary>
public string BookName { get; set; }
/// <summary>
/// 图书所属分类的ID
/// </summary>
public int CateID { get; set; }
}
            // 图书分类示例数据
List<Category> bookCategs = new List<Category>
{
new Category { catID = , catName = "文学类" },
new Category { catID = , catName = "经济管理类" },
new Category { catID = , catName = "机械工程类" },
new Category { catID = , catName = "法律基础类" }
}; // 图书信息示例数据
List<BookInfo> books = new List<BookInfo>
{
new BookInfo { BookID = , BookName = "图书01", CateID = },
new BookInfo { BookID = , BookName = "图书02",CateID = },
new BookInfo { BookID = , BookName = "图书03", CateID = },
new BookInfo { BookID = , BookName = "图书04", CateID = },
new BookInfo { BookID = , BookName = "图书05",CateID = },
new BookInfo { BookID = , BookName = "图书06", CateID = },
new BookInfo { BookID = , BookName = "图书07", CateID = },
new BookInfo { BookID = , BookName = "图书08",CateID = },
new BookInfo { BookID = , BookName = "图书09", CateID = },
new BookInfo { BookID = , BookName = "图书10", CateID = },
new BookInfo { BookID = , BookName = "图书11", CateID = },
new BookInfo { BookID = , BookName = "图书12", CateID = },
new BookInfo { BookID = , BookName = "图书13", CateID = },
new BookInfo { BookID = , BookName = "图书14", CateID = },
new BookInfo { BookID = , BookName = "图书15", CateID = },
new BookInfo { BookID = , BookName = "图书16", CateID = },
};

接下来,联合books和bookCategs两个数据序列,代码如下:

            // 联合查询,并产生新的类型
var qryres = from b in books
join c in bookCategs on b.CateID equals c.catID
select new
{
b.BookName,
c.catName
};
// 输出结果
foreach (var bitem in qryres)
{
Console.WriteLine("图书名:{0},所属分类:{1}", bitem.BookName, bitem.catName);
}

上述代码,select子句使用new运算符动态创建匿名类型,并使用BookInfo对象的BookName属性和Category对象的catName属性作为新类型的属性,也就是说,创建的匿名类型具有BookName和catName两个属性,当然,也可以为动态创建的匿名类型使用自己命名的属性名,代码如下:

            var qryres2 =
from bk in books
join bc in bookCategs on bk.CateID equals bc.catID
select new
{
Book_ID = bk.BookID,
Book_Name = bk.BookName,
Book_Cate = bc.catName
};
// 输出结果
foreach (var bk in qryres2)
{
Console.WriteLine("图书ID:{0},图书名:{1},所属分类:{2}", bk.Book_ID, bk.Book_Name, bk.Book_Cate);
}

在上面的例子中,与每个BookInfo对象实例的CateID属性相对应的Category对象都能在bookCategs列表中找到,这种的联合查询称为”内部联合“。下面,就考虑另一种情况,即当序列A与序列B进行联合查询时,在序列B中找不到与序列A的项匹配的元素。

代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace My
{ #region 定义类型
/// <summary>
/// 专辑信息
/// </summary>
public class Album
{
/// <summary>
/// 专辑名称
/// </summary>
public string Title { get; set; }
/// <summary>
/// 发行年份
/// </summary>
public int Year { get; set; }
/// <summary>
/// 专辑描述
/// </summary>
public string Description { get; set; }
} /// <summary>
/// 曲目信息
/// </summary>
public class Track
{
/// <summary>
/// 曲目名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 艺术家名字
/// </summary>
public string Artist { get; set; }
/// <summary>
/// 所属专辑
/// </summary>
public Album AlbumOf { get; set; }
}
#endregion class Program
{
static void Main(string[] args)
{
// 专辑列表
Album album1 = new Album { Title = "专辑 1", Year = , Description = "这是第一张专辑。" };
Album album2 = new Album { Title = "专辑 2", Year = , Description = "这是第二张专辑。" };
List<Album> albums = new List<Album> { album1, album2 }; // 曲目列表
Track track1 = new Track { Name = "曲目 1", Artist = "艺术家 1", AlbumOf = album1 };
Track track2 = new Track { Name = "曲目 2", Artist = "艺术家 2", AlbumOf = album2 };
Track track3 = new Track { Name = "曲目 3", Artist = "艺术家 3", AlbumOf = album2 };
Track track4 = new Track { Name = "曲目 4", Artist = "艺术家 4", AlbumOf = album1 };
Track track5 = new Track { Name = "曲目 5", Artist = "艺术家 5", AlbumOf = album2 };
Track track6 = new Track { Name = "曲目 6", Artist = "艺术家 6", AlbumOf = null };
List<Track> tracks = new List<Track> { track1, track2, track3, track4, track5, track6 }; // 开始查询
var res1 = from t in tracks
join a in albums on t.AlbumOf equals a into g1
from a1 in g1.DefaultIfEmpty()
select new
{
TrackName = t.Name,
Artist = t.Artist,
AlbumName = a1 == null ? "未知专辑" : a1.Title
}; // 以下代码会发生异常
//var res1 = from t in tracks
// join a in albums on t.AlbumOf equals a into g1
// from a1 in g1.DefaultIfEmpty()
// select new
// {
// TrackName = t.Name,
// Artist = t.Artist,
// AlbumName = a1.Title
// }; // 输出结果
foreach (var item in res1)
{
Console.WriteLine("曲目:{0},艺术家:{1},专辑:{2}", item.TrackName, item.Artist, item.AlbumName);
} Console.WriteLine(); var res2 = from t in tracks
join a in albums on t.AlbumOf equals a into g
from a2 in g.DefaultIfEmpty(new Album { Title = "<未知>", Year = , Description = "<无>" })
select new
{
TrackName = t.Name,
Year = a2.Year,
Artist = t.Artist,
AlbumName = a2.Title,
AlbumDesc = a2.Description
};
// 输出结果
foreach (var item in res2)
{
Console.WriteLine("曲目:{0},年份:{1},艺术家:{2},专辑:{3},专辑描述:{4}", item.TrackName, item.Year, item.Artist, item.AlbumName, item.AlbumDesc);
} Console.Read();
}
}
}

(3) 嵌套查询

嵌套查询是指在一个查询内部嵌套这另一个查询,其实嵌套查询是比较简单的,就直接看个例子吧。

代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace My
{
#region 定义类型
/// <summary>
/// 商品信息
/// </summary>
public class Goods
{
/// <summary>
/// 商品编号
/// </summary>
public string GsNo { get; set; }
/// <summary>
/// 商品名称
/// </summary>
public string GsName { get; set; }
/// <summary>
/// 商品单价
/// </summary>
public double GsPrice { get; set; }
} /// <summary>
/// 销售单信息
/// </summary>
public class SalesOrder
{
/// <summary>
/// 单据ID
/// </summary>
public int OrderID { get; set; }
/// <summary>
/// 商品编号
/// </summary>
public string GoodsNo { get; set; }
/// <summary>
/// 销售时间
/// </summary>
public DateTime Time { get; set; }
/// <summary>
/// 销售数量
/// </summary>
public int Qty { get; set; }
}
#endregion class Program
{
static void Main(string[] args)
{
// 商品信息 - 示例数据
Goods[] goodsArr =
{
new Goods { GsNo = "G-1", GsName = "报纸", GsPrice = 1.50d },
new Goods { GsNo = "G-2", GsName = "食盐", GsPrice = 3.65d },
new Goods { GsNo = "G-3", GsName = "火柴", GsPrice = 0.50d },
new Goods { GsNo = "G-4", GsName = "灯泡", GsPrice = 12.30d },
new Goods { GsNo = "G-5", GsName = "剪刀", GsPrice = 4.50d }
}; // 销售单据 - 示例数据
SalesOrder[] orders =
{
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) },
new SalesOrder { OrderID = , GoodsNo = goodsArr[].GsNo, Qty = , Time = new DateTime(, , ) }
}; /*
* 查询并计算出各个商品的
* 总销售额
*/
var res = from g in goodsArr
let totalQty =
/* 以下为嵌套查询 */
(from od in orders
where od.GoodsNo == g.GsNo
select od).Sum(odr => odr.Qty)
select new
{
g.GsNo,
g.GsName,
/* 计算总销售额 */
Total = totalQty * g.GsPrice
}; // 输出查询结果
foreach (var item in res)
{
Console.WriteLine("编号:{0},商品:{1},总额:{2:N2}", item.GsNo, item.GsName, item.Total);
} Console.Read();
}
}
}

博客写到这,可以看到其实LINQ查询是比较简单的,只要仔细,就不会出错的。。。。

LINQ(集成化查询)的更多相关文章

  1. LINQ to Entities 查询语法

    转自: http://www.cnblogs.com/asingna/archive/2013/01/28/2879595.html 实体框架(Entity Framework )是 ADO.NET  ...

  2. xBIM 使用Linq 来优化查询

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  3. C&num;3&period;0新增功能09 LINQ 基础07 LINQ 中的查询语法和方法语法

    连载目录    [已更新最新开发文章,点击查看详细] 介绍性的语言集成查询 (LINQ) 文档中的大多数查询是使用 LINQ 声明性查询语法编写的.但是在编译代码时,查询语法必须转换为针对 .NET ...

  4. ElasticSearch 5学习&lpar;10&rpar;——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  5. 转linq中的Single&lpar;&rpar;、First&lpar;&rpar;、Take&lpar;1&rpar; LINQ 标准的查询操作符 排序 orderby、thenby、Take

    Single():操作一个集合,同时强要求只有一个对象匹配,并返回这一个. First():操作一个集合,可以有多个对象匹配,但是只返回第一个. Take(1):操作一个集合,可以有对个对象匹配,单只 ...

  6. 浅谈sql 、linq、lambda 查询语句的区别

    浅谈sql .linq.lambda 查询语句的区别 LINQ的书写格式如下: from 临时变量 in 集合对象或数据库对象 where 条件表达式 [order by条件] select 临时变量 ...

  7. LINQ to Entities 查询注意事项

    1> 排序信息丢失 如果在排序操作之后执行了任何其他操作,则不能保证这些附加操作中会保留排序结果.这些操作包括 Select 和 Where 等.另外,采用表达式作为输入参数的 First 和 ...

  8. ElasticSearch&lpar;6&rpar;-结构化查询

    引用:ElasticSearch权威指南 一.请求体查询 请求体查询 简单查询语句(lite)是一种有效的命令行_adhoc_查询.但是,如果你想要善用搜索,你必须使用请求体查询(request bo ...

  9. SQL结构化查询语句

    SQL结构化查询语句 SQL定义了查询所有关系型数据库的规则. 1.通用语法 SQL语句可以单行或者多行书写,以分号结尾 可以使用空格和缩进增强可读性 不区分大小写,但是关键字建议大写 3种注释 注释 ...

随机推荐

  1. &lbrack;LeetCode&rsqb; Guess Number Higher or Lower 猜数字大小

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  2. Linux经典书籍推荐

    入门篇 <LINUX权威指南>书不错,写的很全面也比较广,涉及的不深,做为入门书籍不错,可以比较全面的了解linux .另外比较热门的也可以看看<鸟哥的私房菜>等书,偏管理类的 ...

  3. dojo简单添加一个Panel到父容器中

    this.contentPane = new ContentPane(); this.set("content", this.contentPane.domNode); this. ...

  4. 使用U盘进行Linux系统的安装

    由于目前很多服务器已经本身不配光驱了,最近测试了下使用U盘进行Linux系统的安装,过程比较简单,需要注意的地方如下: 1.找一台linux主机,插入U盘,执行fdisk -l,识别到U盘. 2.将需 ...

  5. ASP&period;NET基础之HttpModule学习

    最近学习WCF知识时看到有关IIS版本的知识,发现对HttpContext,HttpModule,HttpHandler的内容都不是很了解,这三个也是ASP.NET相对基础的内容,晚上特地花点时间针对 ...

  6. IDE、SDK、API

    IDE 集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器.编译器.调试器和图形用户界面等工具.集成了代 ...

  7. zabbix使用SNMPV3协议监控交换机

    SNMPV3是简单网络管理协议的第三版,因为其安全性更高,现在的中低端交换机已普遍支持该协议,所以在生产环境中我们应该采用SNMPV3对交换机.路由器进行管理. 首先在交换机上要配置SNMPV3协议, ...

  8. Unity 灯光系统详解

    Unity 灯光系统详解 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心 ...

  9. MongoDB副本集配置系列四:节点的关闭顺序

    接上一篇博客:http://www.cnblogs.com/xiaoit/p/4522218.html Primary Secondary Arbiter 1:关闭顺序PSA :会报错 2:关闭顺序P ...

  10. struts2 select标签

    headerValue : 默认值value headerKey : 默认name list : 源数据 (可以在action方法里从数据库获取list) name : 被选数据存放的位置(这里我方在 ...