EntityFramework数据持久化复习资料5、LINQ概述与应用(超终点)
前言
微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上。开发人员使用Linq语言,对数据库操作如同操作Object对象
一样省事。EF有三种使用场景,1. 从数据库生成Class,2.由实体类生成数据库表结构,3.通过数据库可视化设计器设计数据库,同时生成实体类。
ORM (对象关系型映射)是将数据存储从域对象自动映射到关系型数据库的工具。ORM主要包括3个部分:域对象、关系数据库对象、映射关系。ORM使类提供自动化CRUD,使
开发人员从数据库API和SQL中解放出来。以前是使用ADO.NET来进行对数据库中得数据表进行操作,现在,使用ORM直接对对象进行操作,操作对象就等于操作数据库表,
那怎么让对象和数据库表一一对应起来?这个过程就是通过ORM框架来完成的,操作对象就是操作数据库也是通过ORM来完成的。ORM框架就是做对象和数据库的映射的。
那么EntityFramework的作用是什么?
我的理解就是大大简化数据库操作的,举个例子:在没有使用EF前,我们要编写复杂的SQL语句,而使用了EF之后,将会减少编写复杂的SQL语句过程。
开发环境
系统环境:win7及以上,本示例环境win11
开发工具:Visual Studio 2017及以上
创建项目:
控制台请创建【控制台应用(.NET Framework)】
Web请创建【ASP.NET Web应用程序(.NET Framework)】
数据库:SQLServer数据库2012及以上版本·如果下载最新版本,使用免费版本即可。
本地数据库链接:【.】或【127.0.0.1】
登陆方式1:【本地登陆】
登陆方式2:账号【sa】 pwd【admin】
测试数据库名称:【mytest】
排序规则:【Chinese_PRC_CI_AS】
LINQ的概述
LINQ(Language Integrated Query,语言集成查询)提供了一种跨数据源和数据格式的统一模型,实现查询。
在LINQ中,可以使用与查询数据库相同的编码模式来查询和转换XML文档、SQL数据库、ADO.NET数据集以及.NET集合中的数据,并支持LINQ查询的任何格式的数据。
LINQ关键字
关键字 |
说明 |
from |
指定范围变量和数据源 |
where |
根据bool表达式从数据源中筛选数据 |
select |
指定查询结果中的元素所具有的类型或表现形式 |
group |
对查询结果按照键/值执行分组 |
into |
提供一个标识符,它可以充当对join、group或select子句结果的引用 |
orderby |
对查询出的元素执行排序(ascending/descending) |
join |
按照两个指定匹配条件对等连接两个数据源 |
let |
产生一个用于存储子表达式查询结果的范围变量 |
LINQ语法
只有实现了【IEnumerable】接口的数据源,才能执行相关的LINQ操作。
from [type] id in source
[join [type] id in source on expr equals expr [into subGroup]]
[from [type] id in source | let id = expr | where condition]
[orderby ordering,ordering,ordering...]
select expr | group expr by key
[into id query]
基础示例
这里我写了一个基础的示例,这个示例返回的是nums数组中所有的偶数。
这个里这个数据集可以使用【数组】/【列表】都可以。
int[] nums = { 123, 42, 13, 5, 346, 45, 23423, 63, 4, 2, 433, 243, 24, 7 }; // 2.创建查询. var LINQ = //from开始 num是每个nums返回的对象,in是固定语法,在的意思 from num in nums //where是筛选,筛选的方式是要偶数 where (num % 2) == 0 //每次返回num结果 select num; //输出测试 foreach (var item in LINQ) { Console.WriteLine(item); }
实际效果:
对象筛选示例
示例类【Users】
创建对象列表
数据初始化函数init()
private static List<Users> init() { List<Users> list = new List<Users>(); list.Add(new Users() {id=1,userName="王语嫣",age=15 }); list.Add(new Users() {id=2,userName="龙姑娘",age=18 }); list.Add(new Users() {id=3,userName="小龙女",age=16 }); list.Add(new Users() {id=4,userName="赵灵儿",age=17 }); list.Add(new Users() {id=5,userName="王语嫣",age=22 }); return list; }
1、LINQ根据id精准查询·返回单个对象
这里我们是单个的id匹配,我们最后需要使用【SingleOrDefault】。
List<Users> list = init(); var linq = (from item in list where item.id == 2 select item).SingleOrDefault(); Console.WriteLine(linq.id); Console.WriteLine(linq.userName); Console.WriteLine(linq.age);
异常效:1:(这里我查询的是20,很明显没有这个ID,故而报了异常)
异常效果2:(数据格式化了一下,我把其中id=2的值写了2个。使用SingleOrDefault查询出两个相同的结果依然会出现异常提示)
一般情況下都会使用【SingleOrDefault】,因为这能直接判断这个唯一的信息是否正确,项目中出现相同的值肯定是有异常的,就可以帮助我们定位异常。
2、LINQ根据【昵称】模糊查询返回列表
模糊查询并遍历·这里用到的是字符串的【Contains】函数,ToList()返回一个列表。
List<Users> list = init(); var linq=(from item in list where item.userName.Contains("龙") select item).ToList(); foreach (var item in linq) { Console.WriteLine(item.id); Console.WriteLine(item.userName); Console.WriteLine(item.age); }
实际效果:
3、LINQ分组查询·返回列表
我们把聂小倩和龙姑娘都改成18岁,我们根据年龄进行分组。
private static List<Users> init() { List<Users> list = new List<Users>(); list.Add(new Users() { id = 1, userName = "王语嫣", age = 15 }); list.Add(new Users() { id = 2, userName = "龙姑娘", age = 18 }); list.Add(new Users() { id = 3, userName = "小龙女", age = 16 }); list.Add(new Users() { id = 4, userName = "赵灵儿", age = 17 }); list.Add(new Users() { id = 5, userName = "聂小倩", age = 18 }); return list; }
基础分组示例代码:
List<Users> list = init(); var linq = (from item in list group item by item.age ).ToList(); Console.WriteLine(linq.Count);
分组效果:
分组示例代码:
List<Users> list = init(); var linq = from item in list //分组后将数据放置到p中 group item by item.age into p //根据p重新创建一个匿名对象返回数据 select new { p.Key, KeyCount = p.Count() }; foreach (var item in linq) { Console.WriteLine(item); }
遍历效果:
4、LINQ排序·返回列表
这里的关键字是orderby,正序是【ascending】倒序是【descending】。
List<Users> list = init(); var linq = from item in list orderby item.age descending select item; foreach (var item in linq) { Console.WriteLine(item.id); Console.WriteLine(item.userName); Console.WriteLine("倒序年龄:"+item.age); }
倒序输出效果:
5、聚合查询
聚合查询共计有5个,但是如果数量较大的计数就需要使用LongCount故而有6个属性
方法名 |
说明 |
Count |
对集合中的元素计数,以及对集合中满足条件的元素计数 |
LongCount |
与Count相同,当Count中元索的个数超过int类型值的上限时使用 |
Max |
确定集合中的最大值 |
Min |
确定集合中的最小值 |
Sum |
计算集合中值的总和 |
Average |
计算集合中值的平均值 |
List<Users> list = init(); //聚合函数 //Count与longCount int count = (from item in list where item.age > 15 select item).Count(); Console.WriteLine("大于15岁的数量:"+count); //max int max = list.Max(o=>o.age); Console.WriteLine("最大年龄:"+max); //min int min = list.Min(o => o.age); Console.WriteLine("最小年龄:" + min); //sum int sum = list.Sum(o => o.age); Console.WriteLine("年龄总数:"+sum); //average double avg = list.Average(o => o.age); Console.WriteLine("平均年龄:"+avg);
输出效果:
6、多表联合查询
重新创建一个UsersDetalis对象,用作多表联合查询示例。
Users列表函数
/// <summary> /// 用户基础信息初始化 /// </summary> /// <returns></returns> private static List<Users> initUsers() { List<Users> list = new List<Users>(); list.Add(new Users() { id = 1, userName = "王语嫣", age = 15 }); list.Add(new Users() { id = 2, userName = "龙姑娘", age = 18 }); list.Add(new Users() { id = 3, userName = "小龙女", age = 16 }); list.Add(new Users() { id = 4, userName = "赵灵儿", age = 17 }); list.Add(new Users() { id = 5, userName = "聂小倩", age = 18 }); return list; }
UsersDetalis列表函数
/// <summary> /// 用户详情 /// </summary> /// <returns></returns> private static List<UserDetails> initUserDetails() { List<UserDetails> list = new List<UserDetails>(); list.Add(new UserDetails() {id=1,uid=1,introduce="琅嬛福地,超级学霸。" }); list.Add(new UserDetails() {id=2,uid=3,introduce="活死人墓,冰山美人。" }); list.Add(new UserDetails() {id=3,uid=4,introduce="灵蛇岛,等着逍遥哥哥。" }); list.Add(new UserDetails() {id=4,uid=5,introduce="聂小倩就是王祖贤" }); return list; }
7、多表联合查询基础示例
使用的关键字是【join】进行链接,匹配id处理笛卡尔积的时候必须使用【equals】做判断。
链接步骤:
1、form第一个列表
2、通过【join】链接另外一个列表
3、通过【on】去掉笛卡尔积
4、筛选、排序、分组操作
5、重新组合匿名对象
//用户表 var list = initUsers(); //用户详情表 var list_details = initUserDetails(); //多表联合查询 var newList = from users in list join usersDetails in list_details on users.id equals usersDetails.uid select new { users_id = users.id, userName = users.userName, age = users.age, users_details_id = usersDetails.id, introduce = usersDetails.introduce }; foreach (var item in newList) { Console.WriteLine(item.users_id); Console.WriteLine(item.userName); Console.WriteLine(item.age); Console.WriteLine(item.users_details_id); Console.WriteLine(item.introduce); Console.WriteLine("-------------------"); }
实际效果:其中id=2的用户龙姑娘在详情表中并没有显示,故而数据中不显示。
8、多表联合查询——模糊查询
where users.userName.Contains("龙")
//用户表 var list = initUsers(); //用户详情表 var list_details = initUserDetails(); //多表联合查询 var newList = from users in list join usersDetails in list_details on users.id equals usersDetails.uid where users.userName.Contains("龙") select new { users_id = users.id, userName = users.userName, age = users.age, users_details_id = usersDetails.id, introduce = usersDetails.introduce }; foreach (var item in newList) { Console.WriteLine(item.users_id); Console.WriteLine(item.userName); Console.WriteLine(item.age); Console.WriteLine(item.users_details_id); Console.WriteLine(item.introduce); Console.WriteLine("-------------------"); }
查询效果:因为只有1个符合,所以正确。
9、多表查询·排序
倒序
orderby users.age descending
正序
orderby users.age ascending
//用户表 var list = initUsers(); //用户详情表 var list_details = initUserDetails(); //多表联合查询 var newList = from users in list join usersDetails in list_details on users.id equals usersDetails.uid orderby users.age descending select new { users_id = users.id, userName = users.userName, age = users.age, users_details_id = usersDetails.id, introduce = usersDetails.introduce }; foreach (var item in newList) { Console.WriteLine(item.users_id); Console.WriteLine(item.userName); Console.WriteLine(item.age); Console.WriteLine(item.users_details_id); Console.WriteLine(item.introduce); Console.WriteLine("-------------------"); }
排序效果:
10、分页查询
- Skip代表从第几条开始查询
- Take代表每页查询几条
//用户表 var list = initUsers(); //用户详情表 var list_details = initUserDetails(); //多表联合查询·分页 var newList = (from users in list join usersDetails in list_details on users.id equals usersDetails.uid select new { users_id = users.id, userName = users.userName, age = users.age, users_details_id = usersDetails.id, introduce = usersDetails.introduce }).Skip(0).Take(2);