项目2.0上线,回想过后杂谈总结基础回顾一番

前言

项目2.0基本已经上线了,之前老大问我最近还有在更博客没,我说没,同事说是不是已经挖掘尽了没有什么可写的了,其实不然,对于项目而言,我们都只是负责项目中的冰山一角,没有一个全局观来看待整个项目,急急忙忙的赶着项目,项目中有很多优秀的地方都值得我去效仿和学习,尤其是老大的技术令我折服,这两天不是太忙,就随手看了下自己写的代码,一脸懵逼,心想这是哪个傻逼写的代码,就像新入职同事看着刚离职交接项目的同事的代码一样复杂的心情,但是项目已经划了基线,除非是bug已经不能轻易再发布了,所以让这份记忆暂且存放自己博客中吧。本篇属于各种杂谈,没有一个统一方向,想到哪里写到哪里。

EntityFramework/EntityFramework Core缓存

之前一直有在谈无论是之前的EntityFramework还是现已经跨平台的EntityFramework Core都有其变更追踪,说白了就是缓存,那么到底怎么知道是缓存了还是没有缓存呢,下面我们来看看例子。首先看看数据库中id=2的数据

上述我们只需知道id = 2和Name = "Jeffcky",下面我们进行如下查询:

        public void Query()
        {
            var blog1 = _efCoreContext.Blogs.Find(2);
            blog1.Name = "Jeff";

            var blog2 = _efCoreContext.Blogs.FirstOrDefault(d => d.Name == "Jeffcky");
            var blog2Name = blog2.Name;

            var compareResult = ReferenceEquals(blog1, blog2);

            var blog3 = _efCoreContext.Blogs.FromSql(@"SELECT TOP (1) [Id], [Name], [Url], [Status], [CreatedTime]
            FROM dbo.[Blog]").Single();

            var compareResult1 = ReferenceEquals(blog1, blog3);
        }

如果不存在缓存那么blog2Name = "Jeffcky"且compareResult = false,compareResult1 = false,但是请看如下演示结果:

如果关闭变更追踪,此时如下则compareResult = false:

            var blog1 = _efCoreContext.Blogs.Find(2);
            blog1.Name = "Jeff";

            var blog2 = _efCoreContext.Blogs
                .AsNoTracking()
                .FirstOrDefault(d => d.Name == "Jeffcky");
            var blog2Name = blog2.Name;

            var compareResult = ReferenceEquals(blog1, blog2);

多次循环遍历数据修改

这样的场景应该很常见,查出一个集合中包含另外一个集合,但是呢,查询出数据后需要对该集合中的另外一个集合数据进行处理,比如查询出中Blog集合中存在Post集合,此时需要将Posts中的集合数据中的Title进行修改,此时你会怎样做呢?怎样做才会更加优雅呢,下面是我原始做法:

        public void Query()
        {
            var blogs = _efCoreContext.Blogs
                .Include(d => d.Posts)
                .ToList();

            foreach (var blog in blogs)
            {
                foreach (var post in blog.Posts)
                {
                    post.Title = "[置顶]EntityFramework之DetectChanges's Secrets(三)(我为EF正名)";
                }
            }
        }

此时到这里任务算是完成了,事后返回再看感觉做法是不是有点low,说到底还是对集合中各种方法了解太少的缘故去看了看对集合操作的扩展方法有两种方法就可规避这种循环遍历问题,很多时候我们需要查找判断一个集合中是否存在满足条件的数据然后进行下一步操作这个时候我们想到会利用Any解决如下:

            var blogs = _efCoreContext.Blogs
                .Include(d => d.Posts)
                .ToList();

            var isExist = blogs.Any(d => d.Status == 0);

            if (isExist)
            { }

又或者全部满足才进行下一步操作,此时利用All判断:

            var blogs = _efCoreContext.Blogs
                .Include(d => d.Posts)
                .ToList();

            var isAllSatisfy = blogs.All(d => d.Status == 0);

            if (isAllSatisfy)
            { }

但是我们只是仅止于此对二者的使用,对于上述循环遍历修改数据的问题就可用All来优雅解决上述遍历恶心的问题:

 

            var blogs = _efCoreContext.Blogs
                .Include(d => d.Posts)
                .ToList();

            blogs.All(b =>
            {
                b.Posts.All(p => { p.Title = "[置顶]EntityFramework之DetectChanges's Secrets(三)(我为EF正名)";return true; });
                return true;
            });

如此优雅的修改集合中集合的数据,可能是个人感觉吧,有了几层循环就感觉特别恶心就想着是不是有更加简洁或者优雅的解决方式,我们追求的是代码的优雅和简洁而不是繁琐和臃肿。 下面我们再来看看其他解决方案,通过SelectMany投影解决:

 

            var blogs = _efCoreContext.Blogs
                .Include(d => d.Posts)
                .ToList();

            var posts = blogs.SelectMany(b => b.Posts);

            foreach (var post in posts)
            {
                post.Title = "[置顶]EntityFramework之DetectChanges's Secrets(三)(我为EF正名)";
            }

如此一看也就一层循环比最土最low的方案甚是优雅别致多了。

那么问题就来了,Select和SelectMany有什么区别哟?

我们直接查看如下二者返回值即可:

 

 或许将上述二者返回值用更具体的返回值类型给出更加明了,如下:

            IEnumerable<IEnumerable<Post>> selectBlogs = blogs.Select(d => d.Posts);

            IEnumerable<Post> selectManyPosts = blogs.SelectMany(b => b.Posts);

由上知Select返回的是Posts集合的集合,即将Blogs中的每一项Posts作为一个集合最外围是这整个每一项的集合,而SelectMany则是返回Blogs中的所有Posts将其作为一个集合而返回。

数字类型集合比较是否相等 

在项目中有这样一个场景:一个产品有许多属性,比如颜色,内存,大小,第一次则是进行创建生成唯一sku,下次可以重新添加属性中的值,比如第一次创建时只添加了属性是颜色,属性值为金色的手机,第二次再来添加属性为颜色,属性值为白色的手机,如此一来则和其他属性值进行重新生成新的sku,但是此时又要保证不能和之前已创建的sku重复,此时就要将每组属性中属性值组成的数据和已组合的属性值进行比较,若存在则跳过,否则则创建sku,由于此时生成的属性值顺序可能又不同,所以此时我将每一组组合的属性值放在List集合中,然后再排序,然后再来比较,但是如何比较两个集合中的数字类型的数据是一样的呢,于是最终转换成了字符串的判断:

            var data1 = new List<int>() { 2, 3, 4, 6, 8, 9 };

            var data2 = new List<int>() { 3, 6, 8, 2, 4, 9 };
            data2.Sort();

            var str1 = string.Join("-", data1.ToArray());
            var str2 = string.Join("-", data2.ToArray());

            var isEquals = str1.Equals(str2);

也算是达到了预期,但是看起来还是有点low,于是今天又去看了看集合中的扩展方法,居然可以直接判断两个集合是否相等的方法,当然这是证对于值类型而言,若是引用类型,引用地址都不一样即使数据一样肯定是不相等的,这点大家都明白就无需我废话了。

            var data1 = new List<int>() { 2, 3, 4, 6, 8, 9 };

            var data2 = new List<int>() { 3, 6, 8, 2, 4, 9 };
            data2.Sort();

            var isSequenEqual = data1.SequenceEqual(data2);

 

 这样一写又比上述将集合转换成数组,然后转换成字符串的形式更加优雅,一步到位,我居然没想到,shit。

 Cast和OfType区别

 在集合中需要对集合数据进行类型转换有Cast和OfType两种形式,例如如下皆可:

            var list = new List<int>() { 2, 3, 4, 6, 8, 9 };

            IEnumerable<string> casList = list.Cast<string>();

            IEnumerable<string> ofTypeList = list.OfType<string>();

上述二者转换皆可,那给出二者转换的意义在哪里呢?这个需要好好想想。

OfType:只是将集合中的数据能/可以转换成需要转换的类型进行转换。

Cast:将集合中所有数据转换成需要转换的类型。

Cast相对OfType而言将鼠标放在此方法上会发现多了如下转换异常的类(InvalidCastException)

例如对如下数据进行类型转换:

            object[] objArray = new object[] { "12345", 12 };
            var objCast = objArray.Cast<string>().ToArray();
            var objOfType = objArray.OfType<string>().ToArray();

上述我们已经讨论过二者的区别,此时利用Cast则转换失败出现InvalidCastException。而OfType则将字符串“12345”进行转换。

 

 

如上Cast和OfType内部本质实现原理如下:

        public  IEnumerable<T> Cast<T>(this IEnumerable source)
        {
            foreach (object o in source)
                yield return (T)o;
        }

        public  IEnumerable<T> OfType<T>(this IEnumerable source)
        {
            foreach (object o in source)
                if (o is T)
                    yield return (T)o;
        }

这样就不难解释Cast是全盘转换,而OfType是满足条件类型才转换。

数据类型正确且对数据进行重复过滤 

对于客户端传过来的数据永不可信,在客户端调用接口时第一时间就要对参数进行校验才进行下一步操作,有这样一个场景,客户端将数据拼接成字符串,我们需要获取其中整型且过滤其中重复以免返回重复数据,如下一个字符串:

 var str = "1,2,4,eee,4,7,8,s,j,1";

自从有了新语法特性出现后,对于TryParse无需再额外定义out类型参数,若转换失败则out类型参数为默认值,如此一来进行如下几行代码即可解决问题。

            var list = new List<int>();
            var str = "1,2,4,eee,4,7,8,s,j,1";
            var splitArray = str.Split(',');
            foreach (var data in splitArray)
            {
                int.TryParse(data, out int intData);
                if (list.Contains(intData) || intData <= 0) { continue; };
                list.Add(intData);
            }

当然则是客户端传来的为字符串,直接返回int数组就无需转换了不是,都可以,办法总是有的,就看如何简便的解决不是,不必纠结于此。

判断引用类型为NULL

有些知识点都了解且都知道,但是没有应用场景,等到有了应用场景却忘却了技术知识点,所以还是要擦亮眼睛,所以需要多看看别人优秀的代码或者开源的东西就知道什么时候该用,什么时候不该用,比如如何判断引用类型是否为空的情况。50%以上的人判断类型是否为NULL,通过如下判断.

            var list = new List<int>() { 1, 2, 3, 4, 5 };
            if (list == null)
            {

            }

你是否还记得ReferenceEquals,它只判断引用类型,值类型永远为false,估计学过就知道这么回事,然而判断引用类型是否为空就可以用它来判断。

            var list = new List<int>() { 1, 2, 3, 4, 5 };
            if (ReferenceEquals(list, null))
            {

            }

关于利用ReferenceEquals来判断为NULL的情况还是看的EntityFramework Core源码,里面判断为NULL都是这么判断,不好听一点就是装装逼,好听一点则是优雅一点,C#语法就是两个字【优雅】,当然在这里并不是想推翻什么或者建议什么,二者皆可,只是想表明任何语法的出现都有其应用场景,有些你很少用到的语法就遗漏了,有时候要适当的去补补基础,去对基础回回炉,这是我想说的观点,且勿断章取义。

总结

无论是日常自学还是项目过后也好,都需要抽时间去整理和总结一下,要不然下次还是会采取同样不合理的方案去解决,上述说述各种方案且不说本质上性能是一样的,至少看起来更加优雅且代码书写量更少不是,而不是一眼放去几层遍历,有时候我们觉得代码有点看不下去这个时候就要想想重构或者是否有更加简洁的方式来实现,这样才能更快成长起来,才能走得更远,技术才能积累的更多,日积月累,总结的多了,技术也就上了,不过是花费半天的功夫而已,哪有现成的事情,有些东西没接触过,亲身验证或者走过坑,也就长见识了,后续会陆陆续续更新项目当中遇到的问题和开始学习VUE,项目一直在用VUE,接下来可能会开始更新VUE,不止于此其他也会同步更新,see u。

时间: 2024-09-24 05:31:28

项目2.0上线,回想过后杂谈总结基础回顾一番的相关文章

百度绿萝2.0上线后,新站该如何做SEO

因为在很多新人的概念里面,SEO就是网络推广,网络推广就是SEO,因此一旦出现有什么影响SEO的新政策出现,业内就会议论纷纷.虽然牟长青是写网络推广博客,但其实关于SEO的文章并不多,因为我一直觉得自己是专注做网络推广的,而不是专业做SEO的.网络推广的手段有很多,比如软文推广,微博营销,微信营销,seo并不是唯一的推广途径. 以前也在博客里分享过自己的一些SEO心得,今天针对百度绿萝2.0上线,看很多站长朋友做优化有点举步维艰的感觉,因此我再分享下自己做SEO的一些心得吧. 其实以前就分享过,

表单-淘宝发布宝贝宝贝规格js单击颜色分类自动生成table 项目今天要上线了,请务必帮忙解决谢谢

问题描述 淘宝发布宝贝宝贝规格js单击颜色分类自动生成table 项目今天要上线了,请务必帮忙解决谢谢 需求:点击一个单选框出现表单 每增加一个下边就添加一个 以此类推 动态添加表单 http://jsbin.com/nejoqulipe/edit?html,output这是在线demo 这是我的邮箱529865274@qq.com,请及时联系我 解决方案 类似下面这样 <!DOCTYPE html> <html> <head> <script src="

团宝网站新的团购项目日前已经上线

曾经轰动一时被冠以"跑路"的团宝网站老板任春雷,昨日通过接受两家媒体专访的形式露面,并带着数千万元的融资意向回来了. 今年1月底,团宝网因资金链断裂,大批商家和消费者的欠款被无限期拖延,团宝网创始人任春雷因不知踪迹而被冠以"跑路"之名.2月后,任春雷仅通过微博向外界表示正在四处筹钱.据任春雷透露,经过四处奔波,终于有投资人有意投资数千万元给团宝网. 记者看到团宝网站新的团购项目日前已经上线.任春雷也在3月5日通过微博确认推出新业务:消费者无需付费,0元获得团购订单号

真羡慕 魔兽6.0上线公司福利放假 满级送iPhone 6

昨日零时,<魔兽世界:德拉诺之王>如约在国服上线.但由于并非休息日,因此多数次日还要上班的小伙伴们只能忍痛关机睡觉.但凡事都有例外,暴雪前大中华区总裁戴锦和Alex今天转发的一条微博显示,国内某公司昨日下发通知,为庆祝魔兽6.0上线和魔兽诞生十周年,特意在11月20日为全体员工放一天带薪假,用于冲级.另外,即使在21日上班之后,打卡时间也延迟到了11:00,持续一周.上班时间还会提供 红牛饮料提神解乏.这样的福利是不是感觉碉堡了?是不是又要感叹别人家的公司了?先别急着羡慕,看完下面的奖励项目之

WebQQ 2.0上线引发质疑 QQ地图同时推出

中介交易 SEO诊断 淘宝客 云主机 技术大厅 WebQQ 2.0 9月14日凌晨消息,腾讯昨日晚间开始公测WebQQ 2.0版本(web2.qq.com),不过这一至少已内测两个多月的产品,也随即招来网友的质疑.此外QQ地图(map.qq.com)也同步上线,地理信息数据由搜搜地图的合作伙伴Mapabc提供. 为解决QQ在办公室等场合被限制使用的尴尬,腾讯2006年研发推出WebQQ产品.最初的版本仅是QQ在网页端的完全复制品.2009年4月,WebQQ正式向全部用户开放公测. 昨日晚间,We

微信5.0上线前夜:开放的困与厄

昨天(8月4日)下午从深圳返京,遭遇北京恶劣天气迫降天津,一路颠簸流离浑身湿透,路上断断续续写下这些文字,也算为这个雷鸣电闪,狂风暴雨的难忘夜晚留下点纪念. 2013年8月5日,它注定将成为一个特殊的日子,还有不到24个小时,微信5.0正式版将向世人揭开其神秘的面纱,之前围绕着它的所有传言.谣言都将尘埃落定,那些求内测资格.关心上线档期的朋友们,你们终于可以不捉急了-- 同时联通微信合作的"微信沃卡"将在 易迅网上开启预定,更巧合的是阿里与微博两者爱情的结晶"淘宝微博版&qu

绿萝2.0上线后外链的建设理论杂谈

绿萝算法的再次重演,打击面更广,字面上来说是打击大站买卖软文和新闻源发布外链,但是从判断措施上来说,论坛.博客的外链也会处于打击范围内,回忆起2012年的打击友链买卖,作为一名SEO行业从业多年的小菜鸟来说,我已经无法想到还有什么外链方式是不被百度打击的.我甚至开始想,以后一个新网站上线,恐怕除了向百度提交外已经不能再通过外链来让蜘蛛抓取网站了,这可能会成为网站被K站的导火索. 这么想来,外链是否已经成为绝唱了呢,其实不然,从百度如此大决心的打击外链上来看,我们几乎已经可以判断出,以后依靠首页锚

我的开源项目从 0 到 1024 的过程

第一次做开源项目,从0到1024个star数量经历了一个多月的开发和维护,从新手到入门(至于之后的阶段,我也还在摸索中).在这里我就来分享一下我的经历吧,希望能够对想做开源但是没行动的小伙伴有所帮助. 项目地址:[传送门] 为什么做这个项目? 最近一段时候在编写项目(APP应用)的时候使用列表控件频率非常高,写着就发现很多代码冗余了,于是就想封装一下,开始做起了代码优化,之前做过类似的优化,于是根据之前的优化经验,最终代码量得到了大幅度的优化.只要原有代码量的30%即可完成显示功能,后来随着项目

腾讯QQ Web2.0 上线 建一站式网络生活平台

摘要: 中国最大的互联网综合服务提供商腾讯公司低调上线了一款名为WebQQ 2.0(web2.qq.com)的项目,在该网站中,腾讯将QQ客户端.搜搜.腾讯浏览器.QQ空间.QQ音乐.邮箱.微博.输入法等 中国最大的互联网综合服务提供商腾讯公司低调上线了一款名为WebQQ 2.0(web2.qq.com)的项目,在该网站中,腾讯将QQ客户端.搜搜.腾讯浏览器.QQ空间.QQ音乐.邮箱.微博.输入法等等旗下产品进行整合,有网友惊呼,腾讯QQ OS已经正式开启了一站式网络生活服务平台. 通过腾讯We