Fork me on GitHub

.net core的学习小结

课程:【.NET 6教程,.Net Core 2022视频教程,杨中科主讲】 https://www.bilibili.com/video/BV1pK41137He/?p=159&share_source=copy_web&vd_source=d944df449598b7e51bbc29cddb033275
 
一:.net core 初识
asp.net core 与传统asp.net form相比,更轻量级,运行速度更快,不与iis耦合,能跨平台。
传统的.netframework依赖 framework运行库,而这种传统的运行库,是系统级的,操作系统上所有依赖与这个运行库的软件都受到这个运行库影响,会出现软件的兼容冲突问题,而.net core 能独立部署,同一台操作系统上的不同.net core程序独立部署就不会相互影响,这种方式更能符合现如今的趋势。
.net standard是一种实现标准,规范,在.net core 运行时库里这种库是没有具体的实现代码,在不同的操作系统下,是由不同的代码逻辑去构造.net core的实现,比如传统的与.net core的实现是由不同路径下的dll实现的,并且用反编译软件查看其代码,发现实现代码是有差异的;而我们在写自己的 standard库时,及非.net系统standard库时,这个standard是有具体实现代码的。
从standard2.1开始,不在支持传统的.net framework了。standard1.0支持.net framework4.5。
.net core程序的发布可以独立发布和依赖发布,独立是不需要安装运行时的,而依赖是需要安装.net core运行时的。
NuGet是一种组件包安装工具,管理组件的依赖关系,能对组件进行升级和降级卸载等操作,帮助开发者更高效的复用组件,提高了开发效率。
.net官方网站:dotnet.microsoft.com
二:异步编程
异步编程,不等同于多线程,它内部的实现是一种switch的状态机,不会加快程序的运行速度。我的理解是,异步在于,服务与当前执行的代码的线程遇到了task时,就不会等待这个task任务执行完毕,顺序执行下去,而是如果这个task耗时稍微长一段时间,那么之前的线程会被线程池调去做其他任务,等await结束后,线程池会再叫一个线程服务当前执行的代码,这个服务线程就是系统执行代码的线程了,不是我们自己建立的线程。
举个例子来说,当在winform中,使用task await执行耗时任务时,是不会阻塞ui线程的执行的,我觉得是ui线程在遇到task时,就不会继续等待这个任务执行了,而是会准备响应ui的其他事件的触发,比如拖动,点击界面这些事件。
在asp.net core中,web服务器里与web程序的交互中,当web程序里有异步时,web服务器的服务线程不会因为web程序执行耗时操作,而在那儿等待,它会处于活动状态,接收web程序新的操作,这样的好处是,同样的web服务器支持的最大并发数,但是异步会提高这个并发的性能。
在异步中,不要用sleep,而是用task.dely(),sleep是阻止服务线程的执行,就会减少并发,而task.dely才是阻止当前任务的执行,不会阻塞服务与代码的线程。
CancellationToken可以提前终止异步任务的执行。
async 关键字,会把方法编译成状态机的语句,这样会降低执行效率,所以当task不需要awiat操作的时候,就不要加async关键字。
当异步遇到yield时,需要用 IAsyncIEnumerable 关键字,yieid关键字也会把代码转为状态机模式。
三、LinqToObject和委托事件
linq 内部使用方法委托,完成对集合的操作。委托是把方法当成变量进行传递,一些回调函数也就是使用的方法委托。委托可用系统提供的Actoin和Func来简化代码。委托使用的地方非常的多。事件利用了委托,事件包含事件源(发布者,触发事件的源头)和订阅者(响应事件的具体方法),事件相当于是观察者模式,能对代码进行解耦,事件用得非常得多。事件可以让类或者对象通知订阅了事件的其他对象和类。事件可以注册也可以取消订阅。
四、控制反转与依赖注入
控制反转的意思,是把创建对象的主动权交给容器。其目的是解耦,让开发者只需在需要时,注入对象,而不需要自己去创建。依赖注入(Dependency Injection,DI)是实现控制反转的其中一种方式,还有一种是服务定位器(ServiceLocator)。服务定位器需要自己通过代码去获取对象,而DI直接可以在构造函数声明形参,然后再构造函数内部赋值成员变量就行了,他们的前提是在容器内注入了对象。
依赖注入的声明周期分为:transient scope single 解释分别是瞬时、一定范围、单例。我的理解是,瞬时,每次通过注入获取的对象都是最新创建的;一定范围,在作用范围内,多次获取的对象是同一个,在asp.net core 中 使用scope注入对象,则同一个请求,多次注入都是获得的同一个对象;单例,在程序的整个周期,在asp.net core中,单例在任何请求获取的都是同一个对象。
五、系统配置
在.net core 中,支持多种配置系统 :文件、环境变量、控制台等。可以把日志的参数绑定到一个类对象。
日志还能够在使用快照选项时在文件更改时,在下一次请求里就被更新,而不需要重启程序。
对于环境变量,命令行,支持json扁平化的配置。
可以自定义代码解析自己的配置类。详见:Zack.AnyDBConfigProvider-main
六、日志系统
日志用于记录系统运行时产生的信息,日志根据信息的重要性分为:Trace
日志可以记录在控制台、文件、数据库等。需要根据每天日志的多少,设置每个日志文件的大小,也可以设置日志文件最大个数。
日志还可以通过日志等级过滤,记录到不同文件里。
SerialLog可以比Nlog更方便的实现json类型的日志,以便分析。
七、EF.Core学习
它是跨平台跨数据库的orm框架,让程序员不用写太多原生sql,也不用考虑sql方言兼容问题。
使用时,结合code-first模式会更方便。
在实体配置上,有两种方式,注解方式和fluentapi方式,前一种与实体定义耦合,后一种是不耦合的,更好。
在数据库主键设置中,如果使用自动增长,会在分布式数据库中,会出现同表id重复的情况,在系统的表合并时,也会有这种情况出现。但是好处时,查询速度快。使用guid,全球唯一,在分布式系统中好用,缺点,无法索引,查询速度慢。
它们可以综合应用,设置自增列为实际主键,但是也加入guid作为代码的逻辑主键。
sqlserver还独有支持Hi/Lo算法,一次分配一个主键段,高并发,分布式也不重复。
CodeFirst脚本迁移:Add-Migration XXX Update-Database XXX
更新到特定脚本(向上向下迁移):Update-Database –TargetMigration: AddBlogUrl
生成指定范围的脚本:Script-Migration D F
可以使用 Scaffold-DbContext命令把已有数据库表映射到项目
ef.core不能再where中使用一些自定义方法及一些复杂的方法虽然编译没问题,但是运行会报错。
在efcore的关系配置中,会自动在数据库创建外键列,但这样使用外键列时,效率会变低,所以可以手动创建外键属性映射到数据库。
有时,er关系中,一对应的一方与很多其他类关联,这时可以配置单项关系,不在一方定义list多方类的集合。
efcore支持配置自引用关系,添加一个父级id就行了,例子,菜单,组织架构。
在一对一关系中,必须显示在一方指定一个外键。
IQueryable 是sql数据库端处理数据,及筛选发生在数据库里,IEnumerable是代码端处理数据,会把所有数据查出来,在内存里筛选。IQueryable是延迟加载,只有真正使用到数据时,才会查询,IQueryable是可以复用的。
efcore还支持原生sql查询。
efcore里的实体状态:已添加,已修改,已删除,未改变,分离。首次跟踪对象时,会创建快照,savechanges,对比值。这样做,对象多了,占内存,效率不高。
efcore是不支持批量新增和修改,删除的,就是因为这个实体状态,如果批量操作,对象的状态就会混乱。在批量操作中,已经删除的对象,可能在efcore中不是已删除的状态,这时efcore一直都有的问题,这时就可以单独写sql语句完成批量操作。有个组件可以:Zack.EFCore.Batch,但还是不能解决对象状态混乱的问题。
AsNotracking意思是不跟踪状态,查询出来的对象,发生修改,删除,efcore就不会跟踪它们的状态了,就无法在savechanges保存已经更改的对象。
在efcore中,可以设置全局查询筛选器,所有查询都会隐式带上这个全局条件,比如使用逻辑删除,就不用每次都写未删除查询条件,也可以在查询中忽略全局条件。
八、锁
悲观锁:更新数据时,锁表或者锁行,在这同时,其他需要操作此表或此行数据的操作被阻塞,虽然操作简单,但并发低,不好。
乐观锁:更新数据时,不锁表锁行,更新时带个查询此列值得条件,这样做,当这个值发生改变,其他更新就找不到要更新的对象,影响行数就为0,就能提醒程序,或通过抛异常的方式。代码层面就可以再次重新查询出新值,再更新。支持高并发,但有aba的问题。更新多列,就比较麻烦。可以使用并发令牌来充当更新的where条件,因为每次操作数据库,其并发令牌列的值都会变。mysql中用datetime类型的属性设置并发列。
九、REST
面向资源的接口定义。
十、缓存
缓存分为客户端缓存,服务端页面缓存和内存缓存。
缓存穿透:数据库和缓存中都不存在的数据却访问量很高,但不命中缓存。特殊值也设置缓存
缓存雪崩:同一时间,大部分缓存失效。设置随机过期时间。
缓存击穿:单个热点key值失效,给数据库带来压力。
缓存应用:菜单,权限,热门商品,高频率访问数据库的请求。
十一、Filter与Middleware
filter是实现aop编程的一种方式。filter是属于一个middlerware的,middleware是更底层的方法,filter是控制器层面的,能拿到控制器层面的数据,而middleware不能。
posted @ 2023-01-13 14:17  HelloLLLLL  阅读(183)  评论(0编辑  收藏  举报