Linq如何使用(四)-哪些地方用,如何用

只要有集合的地方,用到运算基本就会用到Linq,简单的排序,取最大值,平均值,过滤数据,这些使用Linq非常方便,基本上实现了Sql里面常见的各种方法。在微软的EF Core中提供了使用Linq可以便捷查询数据库的数据,而不需要编写大部分数据访问代码,可通过各数据库厂商提供的程序或者第三方提供的程序访问许多不同的数据库。除了EF Core还有国人写的SqlSugar访问数据库,开源,性能也不错,功能没有EF Core多,比如数据迁移。
强调一点,EF Core的一些方法比如Add、SaveChanges,它们是微软提供的方法用来保存到数据库或其它。所以很多常说的使用Linq修改数据库,其实是EF Core或者第三方提供的方法。


下面一段是SqlSugar官方介绍:SqlSugar ORM 5.X 教程
SqlSugar是一款来自未来的ORM,拥有超前的理念,需求领跑第一线,可以毫不夸张的说,在设计理念上就算不更新几年都不会过时,我们每天都会跟踪用户需求,将这些用户需求分类和整理,把有共性的功能都整理出来,经历过长达7年的努力,需求成负增长,已经走向了成熟和完善,是一款真正用了功能齐全的ORM框架,如果你用过EF CORE或者DAPPER肯定会为功能缺失而无奈,该有的功能没有,花里胡哨的一大堆。如果你用SqlSugar, 会给你一个不错的选择, 不断给你惊喜。


Enumerable

继承IEnumerable的都可以使用Linq,它派生出来的类微软文档上好几页,只要和集合搭边,就能用。最常用的集合例如List、Array。
举一个微软的官方例子GroupBy,加了一段补充代码。

class Pet
{
    public string Name { get; set; }
    public double Age { get; set; }
}

public static void GroupByEx4()
{
    // 创建一个Pet对象的集合.
    List<Pet> petsList =
        new List<Pet>{ new Pet { Name="Barley", Age=8.3 },
                       new Pet { Name="Boots", Age=4.9 },
                       new Pet { Name="Whiskers", Age=1.5 },
                       new Pet { Name="Daisy", Age=4.3 } };

    var query = petsList.GroupBy(
        pet => Math.Floor(pet.Age),//返回小于或等于Age的最大整数值,当作Key(keySelector)
        pet => pet.Age,//类似sql中的要查询的列,不写的话类似select *,下面的样例就是
        (baseAge, ages) => new
        {
            Key = baseAge,
            Count = ages.Count(),
            Min = ages.Min(),
            Max = ages.Max()
        });
//再写一个补充,加深理解,和上面结果一样
var query1 = petsList.GroupBy(
    pet => Math.Floor(pet.Age),
    (baseAge, ages) => new
    {
        Key = baseAge,
        Count = ages.Count(),
        Min = ages.Min(p=>p.Age),
        Max = ages.Max(p => p.Age),
    });

    // Iterate over each anonymous type.
    foreach (var item in query)
    {
        Console.WriteLine("\nAge group: " + item.Key);
        Console.WriteLine("Number of pets in this age group: " + item.Count);
        Console.WriteLine("Minimum age: " + item.Min);
        Console.WriteLine("Maximum age: " + item.Max);
    }
    foreach (var item in query1)
    {
        Console.WriteLine("\nAge group: " + item.Key);
        Console.WriteLine("Number of pets in this age group: " + item.Count);
        Console.WriteLine("Minimum age: " + item.Min);
        Console.WriteLine("Maximum age: " + item.Max);
    }

    /*  This code produces the following output:

        Age group: 8
        Number of pets in this age group: 1
        Minimum age: 8.3
        Maximum age: 8.3

        Age group: 4
        Number of pets in this age group: 2
        Minimum age: 4.3
        Maximum age: 4.9

        Age group: 1
        Number of pets in this age group: 1
        Minimum age: 1.5
        Maximum age: 1.5
    */
}

Queryable

与Enumerable,都在程序集System.Linq中,都是对集合的扩展,只是Queryable的方法是对IQueryable的扩展,而Enumerable是对IEnumerable的扩展,方法名字看上去很类似,Why,有啥区别,看看参数发现Queryable里面多了一个Expression,Expression是基类,表示表达式树节点的类派生自该基类。
IQueryable<T>接口继承IEnumerable<T>接口,因此,AsQueryable()就可以转换成IQueryable了。
别懵,下面会稍微解释下用法的区别,不懂的话记得读取数据库这些使用Queryable的方法就行了。
代码演示下GroupBy,还用上面的数据,其实就是多了一个AsQueryable()

//Enumerable方法
var query = petsList.GroupBy(
    pet => Math.Floor(pet.Age),
    pet => pet.Age,
    (baseAge, ages) => new
    {
        Key = baseAge,
        Count = ages.Count(),
        Min = ages.Min(),
        Max = ages.Max(),
    });
//Queryable方法,表达式数
var query1 =petsList.AsQueryable().GroupBy(
    pet => Math.Floor(pet.Age),
    pet => pet.Age,
    (baseAge, ages) => new
    {
        Key = baseAge,
        Count = ages.Count(),
        Min = ages.Min(),
        Max = ages.Max(),
    });

Expression<Func<T, bool>>与Func<T, bool>

Func<T, bool>就是一个委托,不明白的话可以看看前面的文章,主要是(二、三)。
Linq如何使用(一)委托Delegate - 简书 (jianshu.com)
Linq如何使用(二)Lambda 声明委托Delegate
Linq如何使用(三)使用Linq-自己写一个实现方法
先看下下面代码

Func<int, bool> fun1 = num => num < 5;
Expression<Func<int, bool>> exfun1 = num => num < 5;
Console.WriteLine(fun1(4));//true
Console.WriteLine(exfun1.Compile()(4));//true

exfun1调用了一个Compile()方法就是委托了。Expression<Func<T, bool>>是一个表达式树,是不能直接调用,我们再用代码分析下Expression。

Expression<Func<int, bool>> exfun1 = num => num < 5;
var param = exfun1.Parameters[0];
BinaryExpression operation = (BinaryExpression)exfun1.Body;

Console.WriteLine($"参数:{param},方法:{operation}");
//输出              参数:num,方法:(num < 5)
Console.WriteLine($"{operation.Left} {operation.NodeType} {operation.Right}");
//输出              num LessThan 5 
//LessThan就是小于

想深入研究的可以自行查资料,也可以反编译看看生成的东西,简而言之,访问数据库的时候where查询一定要用表达式树,微软会帮我们把条件转换成sql里面的Where,要是使用Enumerable里面的方法就是全表查询出结果再过滤条件了,网上应该很多例子,也可以自己跟踪数据库访问。
ps:某些情况,比如计算大量KPI,需要使用Where,SUM,MAX,表关联等等其它运算操作,仅使用Queryable在数据库层面计算相关结果,会影响数据库性能,可能就会需要Queryable和Enumerable的关联了,应用服务器使用Queryable读取到数据库相关数据,再使用Enumerable内存运算,就可以一定程度上避免数据库的性能瓶颈。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容