01:08
对了对了,我跟你讲这个东西有一个很好的很好的意思,就是麦没开他照样会翻译,所以我现在很担心我哪天是不是麦以为关了,但实际上它那个字还是会跟着那个。我在家里搞一些小动作翻译出来,所以我决定了,以后如果下播,我要重启电脑,稳稳妥。好,那我们开始刚才继继续刚才没讲完的话题,好吧,首先第一个刚才有一位gameport gameport gameport,看一下他能不能翻port。Gameport。嗯,可以,好,那还是没翻译出来,那这位朋友有问说两个集合都拿出来讲是lazy模式有影响吗?嗯,确实是的,你说的没错,如果是放,呃,他其实提到的是EF啊,我跟各位解释一下,就EF当中如果你使用的是funk。
02:11
传入到data set当中,他会认为这个放可能是一个本地验证算法,那么他可能会出现一个什么情况呢?就是。把整个表的数据全都拉到客户端,然后在客户端中运行。这个放。那这明显是一个将数据极大的时候是一个很大的影响,因此如果你能够手动的构建出一个合理的表达式,那么就能够解决。如果你写的是fun。而影射导致一些使用EF过程当中的性能问题,当然这是一个,但是不是我们嗯想要讲这个话题的下一步,因为我们讲这个话题的下一步是你可能需要动态的构建一些动态调用EF,只是因为大家可能用的比较多,比较熟悉,所以今天才专门拿出来讲,但是那位朋友提的问题也是对的。
03:09
如果想要在EF当中正确的使用查询。千万不能出现fun。要使用表达式。好,那么继续刚才的话题。刚才讲到。假设前端传递的是Q,那么你想要用Q加中的key作为属性名去查询,应该如何构建这个表达式?那我们。看这个create f方法,因为这个create方法在上面是用来创建条件用的,那我们注释到第一段,其实也不用注释,首先其实你看到这一行代码的时候就已经知道了,创建一个表达式最简单的方法是什么。写一个拉曼达表达式,赋值给表达式,你就会得到一个表达式是不是得绕,但是这是最简单的办法。
04:12
因为编译器,它会自动的将拉曼达隐式转换为一个表达式。所以通常情况下,这是够的。那么假设我们现在要处理这个name。那我们还是要把这个代码注释掉,那么观察右边这个表达式,它一共包含几个部分,首先第一个X。是参数。然后那个监控号表示这是一个方法,或者说是一个fun,然后它的放里面会返回什么呢。又是一个X,那么这个是参数的属性,这是Java的编译题,呃,这个是read,这是全世界最好用的shop变译器,请不要使用visual studio啊,这个就不用讲啊,去一遍就可以了啊,我们继续讲哈,就是x.level那也是说右边是X的level大于。
05:15
另外一个level。那么我们就按照这个思路来编嘛,对吧,使用刚才那个静态方法expression来先来一个什么参数,参数怎么拼来着啊,其实。哎,老是忘记没事拖堂嘛,是吧,拖堂很正常的呀,多讲几分钟,好,我们来第一个参数,参数是什么呢?Perter对吧?准备说了,那么参数有哪些重载呢?我们按一下CTRLP,看一下第一个type表示的参数的类型,还有一个就是下面一个重载,下面一个存载是type跟name,就是说参数的名字,那我们使用下面一个重载。
06:00
Type是什么呢?我们要构建的表达式是一个呃, Xx.level这个X是一个person,这应该看得出来,因为今天来看这个杰克的人应该都是稍微能够用过EF的朋友。好,这个是type of the person,然后给它起个名字,比如说叫X,那我们就得到了第一个表达式,叫做参数表达式,然后我们给它起个漂亮的名字叫PEP。啊,这个漂亮的名字,漂亮就漂亮仔,它短,然后呢,我们要。获取这个。漂亮的表达式的属性,属性的名字叫level。怎么获取呢?当然又来了expression d属性怎么念啊,Property,所以来了property。然后我们又开始观察重载,重载有哪些呢?Expression点,第一个重载是method in,第二个重载是pro for,第三个重载是type,然后用property name,第四个重载是property name,也就是说如果你传名字好像就可以了,对吧?那我们使用最简单的一个什的property name来做,那我们这里呢,既然传递一个name,那我们还是写死吧,好吧。
07:25
Person d。然后他就停住了,为什么?我看一下这个熊仔的名字。Expression d。诶,这不可以吗?好,我们不管了,平常其实我不是用这个重载,好吧,我们跳过我们使用property那个重载,我们使用property重载应该怎么办呢?首先我们要取得property for,那么你就需要使用反射reflection,那么首先获取这个类型,然后取出其中所有的属性,其实取出一个就可以,这个属性的名字叫做。
08:15
呃,叫啥呢?叫level.level,那么你就取到了一个property。这个inform对应的就是person当中的level的这个property,所以你可以得到给它起个漂亮的名字,比如这是L,好,这个名字实在是太漂亮了,因为太短,然后呢,我们使用property name d property,哦,我知道刚才那个为什么不行,因为重仔的第一个是。我们再点一下CTRLP啊,重载的第一个参数是expression,就是诶怎么出不来。
09:01
算了,我们看这个吧。重载的第一个参数是表达式。为什么到那边去?我们也可以这样看。看得见吗?好,重载的第一个参数是表达式,第二个才是我们刚才需要的,那那第一个为什么是表达式呢?因为一个东西的属性,那你首先得告诉他是哪一个东西。那这个哪一个东西就是参数的level,从这个表达式看是参数的level,所以第一个其实是参数表达式,然后第二个才是LP,那你就得到了这个参数的level属性,所以我们再起一个漂亮的名字,你后面会遇到非常多起漂亮名字的需求,因为当你使用表达式来构建整个表达式的时候,会有很多子表达式,然后你就会纠结于这些名字究竟哪个漂亮,哪个不漂亮。
10:11
有的时候选择太多也是一种罪苦,那我们得到了这个参数表达式,再起一个漂亮的名字,比如说叫嗯,因为是写level,所以就叫level。好的,我们就完成了,那么现在其实可以反过来用刚才呃,使用名字的那个重载,对吧,我们直接使用名字,那这不照样能取得出来是吧,这是level expression,那么有了这个level expression,你因为需要下一步了,Level大于。一个level。所以你需要一个大于的。操作,以及右边的这个操作,那双目运算符左边有了。然后我们先构建右边,然后再构建中间,这是双目运算符通常的一个思路,那么右边怎么构建呢?右边是一个,什么是一个?
11:08
在这个当中,右边是这个常见的参数,那么实际上在这个方法当中,右边就是一个。常量。这个常量的值就是level。那回忆刚才上面常量怎么构建?Expression点,所以我们可以得到右边。点com level,你就得到了一个右边的表达式,那么我们应该干嘛?取一个漂亮的名字,好就叫right了,好就right,然后呢,我们将这个左右两边组合在一起,用什么组合大于。因为我们需要的是一个大于,所以你就需要level d d。
12:02
Great。大于。大于好,左边大于右边,然后你又得到了一个表达式,好了,又到了起名字的关键环节,因为你现在得到的是一个最终的。方法体,那我们取一个叫body好看body xp好得到一个bodyp。这是。整个方法的中间部分。然后到了最后一步,怎么变成X等于大于这个这个等于大于实际上是一个拉曼达,对吧,拉曼达,我再念一遍拉曼达。好吧,他好像翻译不出来,算了,那拉曼达怎么算呢?点X点拉曼达。好了,阿们那有两个方法,一个是上面的这个带泛型的,一个是下面这个不带泛型的,那么在这个场景下,因为我们是知道类型的,所以用泛型的这个,那泛型要传什么呢?传的是这个委托的。
13:10
形状,那么看过上面这个柱子的朋友其实是知道这个委托的形状其实就是这个。传入一个person,返回一个布值。根据后面这个拉曼达表达式,你也可以看出来,它就是传入一个X,得到一个X比较的波值返回,所以这个泛形就是传拉曼达的一个。内部结构,那么这个重载它又有哪些呢?我们又看一眼,首先第一个是body,就是拉的。中间一部分,那么刚才不是这个bodyp嘛,所以得到一个bodyp,然后呢,后面重载是参数,我们看后面这个重载是参数perter expression,所以我们可以得到后面这参数,后面参数是什么呢?是什么是第一次开始的时候李世民的这个perter。
14:05
然后你就得到了一个叫做。最终的一个拉曼达expression。好,我好像画面卡在一个很奇怪的地方,哎,不用介意,不用不用,不用在意,好,我们最后得到一个表达是又来了漂亮的名字,Final,然后返回final expression。我们就完成了。就这么简单的完成了,然后我们编译一下。然后测试就自动的运行了起来,最后它的结果也就出来了。绿色的,我绿了。不对,我为什么又绿了?哎,不重要,结果是对的,也就是说你通过一系列瞎逼操作,得到了一个最终跟上面写的这个表达是一模一样的结果。
15:10
对吧,那么这个一模一样的结果就是你想要的呀,那么接下来回到我们刚才的需求,我们可以回到刚才最原始的需求,假设你现在想要查level大于这个的,但是这个level的名字是放在一个字典当中的。啊,这个好像要两个int,两个int,比如说我再来一个,比如说叫H,那么现在有了,就是假设你有level又有H,假设Q当中传了level就查level,传了H就传H,应该怎么办呢?将上面这个静态方法,我们看一下level写死在哪?Level写死在这对吧,那写死的是一个什么?是一个诶字符串。那把这个字符串改成参数不就行了吗?那我们把这个属性名其实就是属性名对吧,Property property property。
16:10
拿上去,然后。复制在这,然后上面肯定报错了,因为我们这里查的这里是写死的,用level查询的。那我们将刚才下面的level拿上来,点level再编一遍对吧?稳妥,年轻人就该稳妥一点是吧?稍微改一点,编译一下,有个单元测试,一直跑着,这不是很爽的一件事情吗?然后我们就得到一个正确的结果啦,那这是level吗?以及后面的值mean。当然这个时候这个后面名字叫mean level已经不太合适了,我们可以叫。那么这个叫create可能也不合适,对吧,我们换一个名字叫create。
17:09
好无所谓的,反正我也不会起名字,好就是意思,就是说这创建了一个表达式,它的表达式是某个属性的值必须。大于最小值。那我们回顾刚才那个需求,假设前端传递的是一个,这里面有个字典,好,这里有字典,那我们现在写一些判断,好吧,If input.curry content content key是什么呢?比如说是 nameof.person.level然后我们就。哎,其实好像也可以。那个啥,Try get out。Value and value out。
18:09
如果这个字典当中格式化一下,呃,换行一下。如果这个字典当中包含level,并且它能够被诚信成功的转型为int,那么就查询结果当中包含int的。那我们就创建这个filter。它应该等于。这个复制过来,那么这里这里不是重了吗?对吧,这不是重叠了吗?重叠该怎么办?重叠该怎么办,重构一下。提取I提取公共的部分。你看,We are,它会提示你,然后知道level name OK,那么就得到了第一个filter,那我们将这个代码也重构一下,让它能够正常的运行。
19:11
然后好,就这样。然后呢,我们在input当中加入一个参数,Q等于new dictionary。然后又来了,又需要这个内,把这个内移到上面。同样的1000对吧,1000。哦,这是字符串1000,那这个mean level下面没用到了,对吧?下面没用到了,因为我们现在使用的是字典里面的这个level name对应的值,所以把这个level去掉,那么这个测试代码。肯定是要通过的,并且。下面这两行,下面这一坨是要变绿的,因为它肯定会进到这个if当中,然后下面这几个测试都会通过编译一下。
20:09
然后它又霹雳啪啦。就得到一个9R全绿了,那说明我们刚才改造已经有效果了,对吧?那么接下来如果我要查A呢。那很简单,我们先加一些age,好吧,我来看一下less大less大佬的age好像好像是18岁,我记得那下面一个是我的我的我我我我已经很老了,我已经很老了,我已经50岁了,能不能查询一下呃。查询一下这个。Level大于1000的,并且A需要小于20的,就是我们我们经常就需要那些那种是吧,职位很高的,但是呢。但是呢,我们需要那种就那叫什么。
21:02
二十二二十二岁毕业,但是我们需要有30岁工作年龄的人,那么这种人是什么呢?就像大佬这样,职别级别超高,年龄很小,我们称之为天才,然后像我这样就不行了,比较老是吧,老气,看这个直播摄像也知道我比较老气,然后而且不不不扯那么多,我们现在查询一下,咱像level大于1000的,并且年龄要小于40的。那我们就写死吧,那啊,我们传一下DH啊,不对呀,我们没实现小鱼啊。对吧,我们实际是大于,那这样船也不行,那么要大于多少呢?大于就大于40嘛,那就大于40肯定是找不到人的嘛,对吧,就就不存在那种超凡脱俗的变态变态天才,那这个level也写子到里面去算了。
22:08
好。那这个踹还要不要呢?其实也不用了,因为你把这个字典全部遍历一遍,然后把数字都拿出来,反正这个内也能传进去嘛,对吧。我们稍微改造一下好。所以。诶。我们便利所有的条件,Curry。然后得到一个KV对吧,然后把下面这一坨代码一拉一放,K就是这个名字,然后VV是要V是字符串要转换的,所以要int.try pace。
23:09
然后一坨一拉,一副纸一放,然后一副一拉,然后一拉,然后这些删掉,然后保存,然后运行一行会怎么样,就会红掉,因为。根本就没有,根本就没有等级小于啊,等级要大于1000,但是年龄又要大于40的人。没有这样的人。但是假设年龄放宽的对吧,我们现在扩招了是不是,哎,不是扩招,我们现在假设就招童工是十岁,只要你十岁起。等级超过1000,我们的公司都非常欢迎你加入,然后我们再重新编译一下,这个测试就应该通过了。
24:00
因为他会筛选出上面的这个。但是我发现它变红了,那这个时候怎么办呢?这时候说明什么说明什么,说明翻车了。翻车不可怕,可怕的是翻完车复不回来,像刚才那个,那我们接下来看一下到底为什么翻车,我们打开这个单元测试,我刚才从一开始到现在都没打开过这个测试的报错信息是不是?请问群主是相声演员吗?群主就是个逗比,不是相声演员那我也不管了,好,继续讲哈,就是。从刚才到现在一直都没打开过这个单元测试的一个结果,为什么呢?因为我们一直很顺利,但是人生不是一直顺利的,有的时候翻一两次车也是没问题的,那翻完车之后你得是吧倒回来,那倒回来的之后你就要看,诶当时我是怎么翻车的,哎,我是油门踩大了,还是就是说刹车没刹住,诶虽然我也没有车也没也没开过,但是呢,但也测试我们小会开的,那么来看一下这个测试的情况吧,我们打开这个单元测试。
25:13
然后展开。想开一把腰,好了,手动拿一下吧。我们得到的错误呢?在。第48行,我们点击右边的这个48行。就会跳到这里,他的意思是说这个集合当中运行single的时候。Through more than one element exception。哇,这句它居然能翻译,翻译出来好,就是说more than one exception,意思就是说。你的这个列表当中超过了一个元素,那也就是说我们看一下刚才的筛选条件过程当中是不是两个都满足了。
26:01
A level level。要大于1000H。要大于十岁,哎,没错啊,正常应该只筛选出这个呀。是吧,我们想象的是只筛选出这个呀。但是我们忽略了一个很大的问题。首先这个它运行第一次的时候,会先取出level。那也就是说他第一次取出level之后,马上运行下面这一段。那么得到的第一个循环。结果肯定是对的,因为只取level大于1000的。那么for运行第二次的时候呢?对吧,运行第二次的时候,使用的是H大于十进行筛选,所以这个时候H大于十。得到的应该是18。
27:01
50都满足。所以这个抛出异常就在第二次便利的时候。出现了异常。那么问题来了,这并不满足我们刚才的需要。我们想要的是这两个条件。用并且的关系,你看这翻车是不是又翻到刚才第一辆车的坑里面去了?我们没有将两个条件end在一起。好。接下来我们就要。解决这个方式的问题,怎么end起来,这是我们今天的一个核心,也不是一个对一个核心怎么按起来呢?其实我们刚才一开始看到过一个方法重载,就是expression.end。
28:00
这是一个逻辑,它就是将左边跟右边。End在一起。但是。我们在平常写代码的过程当中,左边是什么跟右边是什么才能end在一起啊?左边必须是一个布尔表达式,右边必须是一个布尔表达式,然后两个才能end在一起。所以假设你想要加两个条件end在一起,你的左右必须都是。不表达式。我们写个测试来试一下。刚才这个测试我们试用了,左边是数字,右边是数字,然后加在一起,那么现在就是左边是布尔,右边是布尔,加在一起可以吧,True,然后我们使用expression点什么end,那么这个计算出来得到的结果应该是个不尔值,那么。
29:02
这个不值。他应该是false。这就是。运行出来的一个效果。我们可以跑一下下面这个测试。那我们就会得到下面这个测试通过的,那我们改一下这个,这应该是。Boss。And to,那么下面这个就是这个。得到的结果是false。因此。如果你想将两个表达式。混在一起。那么你这个地方。不应该用放马上把它创建出来,因为我刚才一开始的时候犯的错误是什么呢?一开始如果你是啊,代码先删掉了,如果你是FILTER1跟FILTER2 filter1是什么?是一个lamanda fun。
30:09
是一个LA曼达表达式,而FILTER2又是一个曼达表达式,这两个东西是不能end在一起的。你就好像你希望说。呃,是什么呢,这个。拿去摁这个,比如说这样,从语法上这就是说不通的。你只能将这个跟这个end在一起。所以我们可以稍微改造一下下面这个create range man,让它只创建出。波尔表达式,而不创建出后面最后这个拉曼达,那么我们就可以顺利的最后再将这两个条件end在同一个地方。因此我们又稍微的改造一下这个静态方法,诶,只剩一分钟了,好,我们快速的改造一下这个静态方法。
31:05
我们可以得到左边是一个表达是。我们叫啊inner,我们不如叫inner block,好吧,Block,那这样子你就得到了。这样的一个表达式点,你看我们从上往下读点,这个时候perter其实也就不用了。啊,我们是,哦,我们需要一个parameter,那这个parameter必须是同一个,因此我们这个地方使用参数从外面传递进来。A应该是。Input EP啊,那就是这个,然后我们需要一个内部的表达式。
32:07
对的。我们假设这个P就是这个X,那我们取这个P的值。并且右边,然后放在一起,那么你得到的就是上面这个。那么有了这个,你就可以完成两个表达式的end,然后我们再回过去改上面这个。那么这个时候呢?你需要加两个条件end在一起,所以你需要一个列表把它们保存在一起。好吧,好像已经休息了,我们稍微把这写完好吗?Filter等于一个list expression,然后我们将第一个filter放入这个expression,那这个时候这个filter就不能使用这个来创建了,应该是这个。
33:10
那这个呢,我们刚刚不是需要一个parameter吗?所以我们外面需要创建一个parameter expression.parameter啊,Type是。是啥来着?Person X input,然后我们需要将这个传递在这里,然后下面一段拿到外面断言。还有课间时间,是的呀,我其实我如果一直讲的话,你们是会睡着的,我自己可能很兴奋,但是我觉得你们听着听着就需要花不完了,所以正常来说是要课间时间大家互动一下,哎,不多说那些,我们先把这个写完,然后我们把干两个左边右边都放在一起了,最后怎么样,最后end在一起,End在一起。
34:11
怎么end在一起啊,点list,然后end,然后为。啊,一种一种方式就是创建一个我们不是end吗。什么东西跟true end都是true,都是他自己对吧,能不能创建一个true表达式,就是这叫seed,然后for。List item,然后C等于expression.c的item,这就加两个。End在一起的,然后为什么报错了,我看一下里面。里面是一个。
35:01
不能将binary转成expression,好,不能将binary转成expression,强转暴力一点。人生在世,有的时候就需要暴力一点。诶,这是啥哦,这是空啊,这是空,好我们再改一下好可以了,改下这上面的问题,然后我们最后这个C的就是那个结果对吧,然后C的就是那个结果,那我们C的要变成什么呀。刚才删掉的代码是什么?删掉是阿曼达这个这这这一大坨,所以你要把这一大坨拿上来。然后把CD放在中间,把input ESP放进来,最后最后我们就得到了一个。哎,为什么又出现了啊,这里中间变量it名字无所谓啦,洒洒水啦,我这里动这个地方随便起什么都可以啊,然后我直接编译一下,这次应该是可以通过的啦,这要是不通过,哼,肯定是绿的,我也不会立什么flag,已经绿了,已经绿了,朋友们。
36:17
是不是有?好,那么这一阶段的内容又结束了。回顾一下这一阶段的内容,而且不知不觉已经九点了,我打算等一下再讲一集就差不多了,我不知道你们什么时候睡觉,但我打算再讲一集,好吧,下一集讲完差不多了啊。我们回顾一下刚才这一节讲的内容,这一节讲的内容就是如何构建这个。如何使用下面这一大坨东西?来构建这个。其实跟平常写代码是一样的,你需要参数,需要属性,需要常量,需要大于等于需要了么?
37:02
以及两个如何end在一起,对吧?你需要创建两个部分,然后。End在一起。这就是刚才过去的25分钟,我讲的内容其实不止,应该有40分钟,好,那我们现在继续休息。后面一节我们来稍微提一下。开发过程当中,如果你想要如何查询这些表达式,嗯,去哪里找的问题?好,我们现在开始休息好吗?下课课间操。
我来说两句