logo资料库

Entity Framework技术系列之7:LINQ to Entities.pdf

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
Entity Framework 技术系列之 7:LINQ to Entities LINQ to Entities 摘要:本文介绍 LINQ to Entities 的相关概念、基本语法,以及如何使用 LINQ to Entities 消费 Entity Framework 实体数据模型,实现各种查询功能。 前言 LINQ(Language Integrated Query,语言集成查询)是一组用于 C#和 VB.NET 语言 的扩展,它允许编写 C#或者 VB.NET 代码,以与查询数据库相同的方式操作内存数据。LINQ 提供了丰富的类似 SQL 的查询语法,功能强大且容易上手。下图汇总展示了 LINQ 技术的 官方实现集合: 图 1 官方 LINQ 实现汇总图 正如上图所示,LINQ to Entities 是 LINQ 技术在实体对象模型中的一种实现,它与 LINQ to SQL 以及 LINQ to DataSets 一起构成了 LINQ to ADO.NET。LINQ to Entities 可以生成 eSQL,并支持使用 LINQ 语法对实体框架服务层进行查询。下图展示了 LINQ to Entities 消 费实体数据模型的技术细节: 艺林博客:http://yilin.cnblogs.com/ 1 LanguageDataLINQLINQ to ObjectsVB.NET…Database…C#LINQ to SQLLINQ to DataSetsLINQ to EntitiesLINQ to DataSourceLINQ to XML/XSD……Memory ObjectsEntity Data ModelASP.NETXML or XSD Files
Entity Framework 技术系列之 7:LINQ to Entities 图 2 LINQ to Entities 与实体数据模型对应图 相关概念 在开始了解 LINQ to Entities 之前,需要先对.NET Framework 3.5 版本后对 C#语言的 几个扩展特性做一些阐释,这有助于我们更容易、更深刻的理解 LINQ to Entities 技术的原 理与实现。 一、隐式实例化局部变量 .NET Framework 3.5 后,实例化局部变量语法有了新的选择:使用“var”关键字隐式 类型化: var user = new User(); 隐式类型化语法与 Javascript 语言里声明变量的语法类似,它可以一定程度上简化实例 化局部变量的语法。但如果隐式实例化的作用仅限于此,那本文不会专门提及。隐式类型化 更重要的用途是用于匿名类型的实例化。 需要提醒注意的是,只有局部变量实例化允许使用隐式实例化语法。这表示私有变量实 例化无法享受该福利;同时,仅声明变量或实例化对象为 null 也是不允许使用隐式实例化 语法的。 二、对象初始化 对象初始化指在实例化对象时,即可对对象的属性进行赋值: 艺林博客:http://yilin.cnblogs.com/ 2 DataCommandLINQ to Entities对象服务层概念层(CSDL)映射层(MSL)物理数据存储(SSDL)Entity SQL(eSQL)EntityClient和表达式树SQL方言关系数据库存储
Entity Framework 技术系列之 7:LINQ to Entities var user = new User() { ID = Guid.NewGuid(), Account = "Apollo" }; 三、匿名类型 LINQ to Entities 的 Select 可以将实体类型投影为匿名类型,所以有必要对匿名类型作 简单介绍。匿名类型指的是不显示声明类型的细节,而是根据上下文环境需要,临时声明满 足需要的类型。由于该类型是临时需要的,所以不必为之命名。匿名类型的声明语法如下: var user = new { ID = Guid.NewGuid(), Name = "Apollo" }; 四、扩展方法 扩展方法是微软为扩展已有框架而创造的一个语法糖,.NET Framework 3.5 就是通过 很多扩展方法实现了对.NET Framework 2.0 的升级扩展的。扩展方法很神奇,被扩展的对 象可以不知道扩展方法的存在,就能在行为上得到扩展。扩展方法也很蹩脚,如果使用者不 知情,很可能不知道对象具有扩展行为;抑或知道有扩展方法,但是不知道要引用哪个扩展 库以使其支持扩展的行为。扩展方法的语法如下: public static class UserExt { public static void Drink(this User user, object water) { … } } 五、Lambda 表达式 Lambda 表达式是由委托以及匿名方法发展而来的,它可将表达式或代码块(匿名方法) 赋 给 一 个 变 量 , 从 而 以 最 少 量 的 输 入 实 现 编 码 目 的 。 Lambda 表 达 式 一 般 配 合 IEnumerable的静态扩展方法使用,完成对象集合的快捷查询操作。Lambda 表达式的 语法如下: var user = db.Users.FirstOrDefault(o => o.Account == "Apollo"); 六、标准查询操作符 System.Linq.Enumerable 静 态 类 声 明 了 一 套 标 准 查 询 操 作 符 ( Standard Query Operators,SQO)方法集合。标准查询操作符的语法和标准 SQL 很相似,这不是偶然, 而是微软有意为之,以使熟悉 SQL 的程序员们更容易上手。标准查询操作符的基本语法如 下: 艺林博客:http://yilin.cnblogs.com/ 3
Entity Framework 技术系列之 7:LINQ to Entities using (var db = new EntityContext()) { var roles = from o in db.Users where o.Account == "Apollo" select o.Roles; … } 标准查询操作符和 Lambda 表达式的关系非常密切。编译器会将上诉表达式转化为下 列以 Lambda 表达式为参数的显式扩展方法调用序列: using (var db = new EntityContext()) { var roles = db.Users.Where(o => o.Account == "Apollo").Select(o => o.Roles); } 标准查询操作符 接下来,将针对数据查询操作中常用的条件查询、投影、分区、排序、分组、集合、元 素、量词和聚集等标准查询操作符进行分类介绍。 一、条件操作符 条件操作符 Where 类似于 SQL 中的 WHERE 子句,用于实现条件查询。下列扩展方 法表达式查询满足条件“角色不为空”的用户集合: var user = db.Users.Where(o => o.Roles != null); 对应的标准查询操作符表达式为: var users = from o in db.Users where o.Roles != null select o; 二、投影操作符 投影操作符 Select 类似于 SQL 中的 SELECT 子句,将对象投影为一个匿名类型实例, 用于控制指定查询迭代器显示或者处理的对象属性。另外,需要注意的是,扩展方法表达式 中的 Select 操作符并非必须的,省略模式下,会返回完整的被投影对象。下列扩展方法表 达式将用户的帐号和密码信息投影为一个匿名类型: var users = db.Users.Select(o => new { o.Account, o.Password }); 对应的标准查询操作符表达式为: var users = from o in db.Users 艺林博客:http://yilin.cnblogs.com/ 4
Entity Framework 技术系列之 7:LINQ to Entities select new { o.Account, o.Password }; 三、分区操作符 分区操作符实现对象的分区操作。其中,Take 操作符类似于 SQL 中的 TOP 操作符, 下列扩展方法表达式返回前 5 个用户对象: var users = db.Users.OrderBy(o => o.Roles.Count).Take(5); Skip 操作符用于跳过指定个数对象并返回序列中的剩余对象,下列扩展方法表达式返 回除前 10 个用户外的剩余用户: var users = db.Users.OrderBy(o => o.Roles.Count).Skip(10); TakeWhile 操作符用于返回条件表达式值为真时的相邻元素集合,下列扩展方法表达式 返回第一个拥有 3 个角色的用户之前的所有用户集合: var users = db.Users.OrderBy(o => o.Roles.Count).TakeWhile(o => o.Roles.Count == 3); SkipWhile 操作符用于跳过条件表达式值为真时的元素,并返回剩下的元素集合,下列 扩展方法表达式返回第一个拥有 3 个角色的用户之后的所有用户集合: var users = db.Users.OrderBy(o => o.Roles.Count).SkipWhile(o => o.Roles == 3); 四、排序操作符 排序操作符实现对象的排序功能,包括 OrderBy、OrderByDescending、ThenBy、 ThenByDescending 和 Reverse 五个操作符。其中 OrderBy 操作符实现对象的升序排列, 相当于 SQL 中的 ORDER BY ASC 子句,下列扩展方法表达式实现用户按拥有的角色数进 行升序排列: var users = db.Users.OrderBy(o => o.Roles.Count); 对应的标准查询操作符表达式为: var users = from o in db.Users orderby o.Roles.Count select o; OrderByDescending 操作符实现对象的降序排列,相当于 SQL 中的 ORDER BY DESC 子句,下列扩展方法表达式实现用户按拥有的角色数进行降序排列: var users = db.Users.OrderByDescending(o => o.Roles.Count); 对应的标准查询操作符表达式为: var users = from o in db.Users orderby o.Roles.Count descending select o; 艺林博客:http://yilin.cnblogs.com/ 5
Entity Framework 技术系列之 7:LINQ to Entities ThenBy、ThenByDescending 和 Reverse 操作符只能针对 IOrderedEnumerable 接口 对象使用,所以一般紧跟在 OrderBy/OrderByDesending 操作符方法后使用。ThenBy 操作 符由编译器翻译为对 OrderBy 操作符的再次调用;ThenByDescending 操作符由编译器翻 译为对 OrderByDescending 操作符的再次调用;Reverse 操作符实现对象的排序反向。这 里不再一一举例。 五、分组操作符 分组操作符 GroupBy 类似于 SQL 中的 GROUP BY 子句,实现对象的分组操作。下列 扩展方法表达式实现用户对象按拥有的角色数量进行分组: var users = db.Users.GroupBy(o => o.Roles.Count); 对应的标准查询操作符表达式为: var users = from o in db.Users group o by o.Roles.Count into g select new { RoleCount = g.Key, Group = g }; 六、集合操作符 集合操作符包括 Distinct、Union、intersect 和 Except 四个操作符,除 Distinct 外,其 他三个操作符都可将两个序列组合成一个序列。Distinct 操作符类似于 SQL 中的 DISTINCT 关键字,用于删除序列中具有重复值的对象。下列扩展方法表达式实现将用户角色中的重复 角色删除功能: var roles = user.Roles.Distinct(); Union 操作符类似于 SQL 中的 UNION 关键字,用于求具有同样结构的两个序列的并 集。下列扩展方法表达式实现将用户 1 和用户 2 所拥有的角色组合成一个角色集合,并排 除其中重复的角色: var roles = user1.Roles.Union(user2.Roles); Intersect 操作符类似于 SQL 中的 INTERSECT 关键字,用于求具有同样结构的两个序 列的交集。下列扩展方法表达式返回用户 1 和用户 2 都具有的角色集合: var roles = user1.Roles.Intersect(user2.Roles); Except 操作符类似于 SQL 中的 EXCEPT 关键字,用于返回第一个序列中有、但第二 个序列中没有的对象集合。下列扩展方法表达式返回用户 1 拥有,而用户 2 没有的角色集 合: var roles = user1.Roles.Except(user2.Roles); 七、元素操作符 艺林博客:http://yilin.cnblogs.com/ 6
Entity Framework 技术系列之 7:LINQ to Entities 元素操作符包括两组操作符,分别是用于从一个 IEnumerable序列中返回满足条件 的单个对象或无满足条件对象时抛异常的 First、Last 和 Single 操作符,以及返回满足条件 的 单 个 对 象 或 无 满 足 条 件 对 象 时 返 回 空 对 象 的 FirstOrDefault 、 LastOrDefault 和 SingleOrDefault 操作符。其中 First 和 FirstOrDefault 操作符用于返回第一个满足条件的对 象。下列扩展方法表达式返回第一个拥有三个角色的用户: var user = db.Users.FirstOrDefault(o => o.Roles.Count == 3); Last 和 LastOrDefault 操作符用于返回最后一个满足条件的对象。下列扩展方法表达式 返回最后一个拥有三个角色的用户: var user = db.Users.LastOrDefault(o => o.Roles.Count == 3); Single 和 SingleOrDefault 操作符用于返回满足条件的序列中的唯一元素,如果序列中 包含不止一个元素,将会抛异常。下列扩展方法表达式返回帐号为“Apollo”的唯一用户, 如果有多个用户帐号都为“Apollo”,则抛异常: var user = db.Users.SingleOrDefault(o => o.Account == "Apollo"); 八、量词操作符 量词操作符包括 Any、All 和 Contains 三个操作符,用于检查序列中是否有一些对象或 所有对象满足条件。其中,Any 操作符用于检查序列中是否有任何一个对象满足条件。下列 扩展方法表达式当有任何一个用户拥有三个角色时返回真,否则返回假: var result = db.Users.Any(o => o.Roles.Count == 3); All 操作符用于检查序列中是否所有对象均满足条件。下列扩展方法表达式当所有用户 均拥有三个角色时返回真,否则返回假: var result = db.Users.All(o => o.Roles.Count == 3); Contains 操作符用于检查序列中是否包含指定的对象。下列扩展方法表达式当集合中 包含用户 1 则返回真,否则返回假: var result = db.Users.Where(o => o.Roles.Count == 3).Contains(user1); 九、聚集操作符 聚集操作符包括 Count、Min、Max、Sum 和 Average 等多个操作符,用于对对象集合 进行统计计算。其中,Count 操作符类似于 SQL 中的 COUNT 关键字,用于计算序列中满 足条件的对象个数。下列扩展方法表达式返回拥有 3 个角色的用户数量: var result = db.Users.Count(o => o.Roles.Count == 3); Min 操作符类似于 SQL 中的 MIN 关键字,用于返回按条件计算的最小值。下列扩展方 艺林博客:http://yilin.cnblogs.com/ 7
Entity Framework 技术系列之 7:LINQ to Entities 法表达式返回拥有最少角色数量的用户所拥有的角色数量: var result = db.Users.Min(o => o.Roles.Count); Max 操作符类似于 SQL 中的 MAX 关键字,用于返回按条件计算的最大值。下列扩展 方法表达式返回拥有角色数量最多的用户所拥有的角色数量: var result = db.Users.Max(o => o.Roles.Count); Sum 操作符类似于 SQL 中的 SUM 关键字,用于返回按条件计算的总数。下列扩展方 法表达式返回已赋予用户的所有角色总数: var result = db.Users.Sum(o => o.Roles.Count); Average 操作符类似于 SQL 中的 AVERAGE 关键字,用于返回按条件计算的平均值。 下列扩展方法表达式,用于返回用户所拥有的角色平均数: var result = db.Users.Average(o => o.Roles.Count); 总结 本文首先给出了 LINQ 技术的官方实现集合,以及 LINQ to Entities 实现的技术细节; 然后概要介绍了与 LINQ to Entities 相关的几个基本概念;最后对 LINQ to Entities 常用的标 准查询操作符的使用进行了分类介绍,从中也可以看出 LINQ to Entities 和 SQL 的功能基本 是一一对应的。 下一篇文章将综合运用本系列前文所介绍的所有技术,完成一个 RBAC 模型的设计与 实现。 艺林博客:http://yilin.cnblogs.com/ 8
分享到:
收藏