[开源] .Net orm FreeSql 1.5.0 最新版本(番号:好久不见)

废话开头

这篇文章是我有史以来编辑最长时间的,历时 4小时!!!原本我可以利用这 4小时编写一堆胶水代码,真心希望善良的您点个赞,谢谢了!!

很久很久没有写文章了,上一次还是在元旦发布 1.0 版本的时候,今年版本规划是每月底发布小版本(年底发布 2.0),全年的开源工作主要是收集用户需求增加功能,完善测试,修复 bug。FreeSql 1.0 -> 1.5 相隔半年有哪些新功能?只能说每个功能都能让我兴奋,并且能感受到使用者也一样兴奋(妄想症)。

迫不及待的人会问,这更新速度也太快了吧,升级会不会有问题?

  • 不了解版本的更新日志,直接升级不是好的习惯,建议关注我们的更新日志(github 上有专门的文档);

  • 我们的版本开发原则:在尽量保证兼容的情况下,增加新功能,砍掉少量不合理的功能;

  • 我们的单元测试数量:4000+,这是我们引以自豪,发布版本的保障;

2|0入戏准备

FreeSql 是 .Net ORM,能支持 .NetFramework4.0+、.NetCore、Xamarin、XAUI、Blazor、以及还有说不出来的运行平台,因为代码绿色无依赖,支持新平台非常简单。目前单元测试数量:4000+,Nuget下载数量:123K+,源码几乎每天都有提交。值得高兴的是 FreeSql 加入了 ncc 开源社区:https://github.com/dotnetcore/FreeSql,加入组织之后社区责任感更大,需要更努力做好品质,为开源社区出一份力。QQ开发群:4336577

为什么要重复造轮子?

FreeSql 主要优势在于易用性上,基本是开箱即用,在不同数据库之间切换兼容性比较好。作者花了大量的时间精力在这个项目,肯请您花半小时了解下项目,谢谢。

FreeSql 整体的功能特性如下:

  • 支持 CodeFirst 对比结构变化迁移;

  • 支持 DbFirst 从数据库导入实体类;

  • 支持 丰富的表达式函数,自定义解析;

  • 支持 批量添加、批量更新、BulkCopy;

  • 支持 导航属性,贪婪加载、延时加载、级联保存;

  • 支持 读写分离、分表分库,租户设计;

  • 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/达梦/MsAccess;

1.0 -> 1.5 更新的重要功能如下:

一、UnitOfWorkManager 工作单元管理器,可实现 Spring 事务设计;

二、IFreeSql.InsertOrUpdate 实现批量保存,执行时根据数据库自动适配执行 merge into 或者 on duplicate key update;

三、ISelect.WhereDynamicFilter 方法实现动态过滤条件(与前端交互);

四、自动适配表达式解析 yyyyMMdd 常用 c# 日期格式化;

五、IUpdate.SetSourceIgnore 方法实现忽略属性值为 null 的字段;

六、FreeSql.Provider.Dameng 基于 DmProvider Ado.net 访问达梦数据库;

七、自动识别 EFCore 常用的实体特性,FreeSql.DbContext 拥有和 EFCore 高相似度的语法,并且支持 90% 相似的 FluentApi;

八、ISelect.ToTreeList 扩展方法查询数据,把配置父子导航属性的实体加工为树型 List;

九、BulkCopy 相关方法提升大批量数据插入性能;

十、Sqlite :memrory: 内存模式;

FreeSql 使用非常简单,只需要定义一个 IFreeSql 对象即可:

static IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, connectionString).UseAutoSyncStructure(true) //自动同步实体结构到数据库.Build(); //请务必定义成 Singleton 单例模式

 

3|0UnitOfWorkManager 工作单元管理器

public class SongService
{BaseRepository<Song> _repo;public SongService(BaseRepository<Song> repo){_repo = repo;}[Transactional]public virtual void Test1(){_repo.Insert(new Song { Title = "卡农1" }); //事务1this.Test2();}[Transactional(Propagation = Propagation.Nested)] //嵌套事务,新的(不使用 Test1 的事务)public virtual void Test2(){_repo.Insert(new Song { Title = "卡农2" });}
}

BaseRepository 是 FreeSql.BaseRepository 包实现的通用仓储类,实际项目中可以继承它再使用。

Propagation 的模式参考了 Spring 事务,在以下几种模式:

  • Requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。

  • Supports:支持当前事务,如果没有当前事务,就以非事务方法执行。

  • Mandatory:使用当前事务,如果没有当前事务,就抛出异常。

  • NotSupported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • Never:以非事务方式执行操作,如果当前事务存在则抛出异常。

  • Nested:以嵌套事务方式执行。(上面的例子使用的这个)

UnitOfWorkManager 正是干这件事的。避免了每次对数据操作都要现获得 Session 实例来启动事务/提交/回滚事务还有繁琐的Try/Catch操作。这些也是 AOP(面向切面编程)机制很好的应用。一方面使开发业务逻辑更清晰、专业分工更加容易进行。另一方面就是应用 AOP 隔离降低了程序的耦合性使我们可以在不同的应用中将各个切面结合起来使用大大提高了代码重用度。

使用前准备第一步:配置 Startup.cs 注入

//Startup.cs
public void ConfigureServices(IServiceCollection services)
{services.AddSingleton<IFreeSql>(fsql);services.AddScoped<UnitOfWorkManager>();services.AddFreeRepository(null, typeof(Startup).Assembly);
}
UnitOfWorkManager 成员说明
IUnitOfWork Current返回当前的工作单元
void Binding(repository)将仓储的事务交给它管理
IUnitOfWork Begin(propagation, isolationLevel)创建工作单元

使用前准备第二步:定义事务特性

[AttributeUsage(AttributeTargets.Method)]
public class TransactionalAttribute : Attribute
{/// <summary>/// 事务传播方式/// </summary>public Propagation Propagation { get; set; } = Propagation.Requierd;/// <summary>/// 事务隔离级别/// </summary>public IsolationLevel? IsolationLevel { get; set; }
}

使用前准备第三步:引入动态代理库

在 Before 从容器中获取 UnitOfWorkManager,调用它的 var uow = uowManager.Begin(attr.Propagation, attr.IsolationLevel) 方法

在 After 调用 Before 中的 uow.Commit 或者 Rollback 方法,最后调用 uow.Dispose

自问自答:是不是进方法就开事务呢?

不一定是真实事务,有可能是虚的,就是一个假的 unitofwork(不带事务),也有可能是延用上一次的事务,也有可能是新开事务,具体要看传播模式。

4|0IFreeSql.InsertOrUpdate 批量插入或更新

IFreeSql 定义了 InsertOrUpdate 方法实现批量插入或更新的功能,利用的是数据库特性进行保存,执行时根据数据库自动适配:

DatabaseFeatures
MySqlon duplicate key update
PostgreSQLon conflict do update
SqlServermerge into
Oraclemerge into
Sqlitereplace into
Damengmerge into
fsql.InsertOrUpdate<T>().SetSource(items) //需要操作的数据.ExecuteAffrows();

由于我们前面定义 fsql 变量的类型是 MySql,所以执行的语句大概是这样的:

INSERT INTO `T`(`id`, `name`) VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)

当实体类有自增属性时,批量 InsertOrUpdate 最多可被拆成两次执行,内部计算出未设置自增值、和有设置自增值的数据,分别执行 insert into 和 上面讲到的 merge into 两种命令(采用事务执行)。

5|0WhereDynamicFilter 动态过滤

是否见过这样的高级查询功能,WhereDynamicFilter 在后端可以轻松完成这件事情,前端根据 UI 组装好对应的 json 字符串传给后端就行,如下:

DynamicFilterInfo dyfilter = JsonConvert.DeserializeObject<DynamicFilterInfo>(@"
{""Logic"" : ""Or"",""Filters"" :[{""Field"" : ""Code"",""Operator"" : ""NotContains"",""Value"" : ""val1"",""Filters"" :[{""Field"" : ""Name"",""Operator"" : ""NotStartsWith"",""Value"" : ""val2"",}]},{""Field"" : ""Parent.Code"",""Operator"" : ""Eq"",""Value"" : ""val11"",""Filters"" :[{""Field"" : ""Parent.Name"",""Operator"" : ""Contains"",""Value"" : ""val22"",}]}]
}
");
fsql.Select<VM_District_Parent>().WhereDynamicFilter(dyfilter).ToList();
//SELECT a.""Code"", a.""Name"", a.""ParentCode"", a__Parent.""Code"" as4, a__Parent.""Name"" as5, a__Parent.""ParentCode"" as6 
//FROM ""D_District"" a 
//LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode"" 
//WHERE (not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%')

支持的操作符:Contains/StartsWith/EndsWith/NotContains/NotStartsWith/NotEndsWith、Equals/Eq/NotEqual、GreaterThan/GreaterThanOrEqual、LessThan/LessThanOrEqual

6|0表达式解析 yyyyMMdd c# 常用日期格式化

不知道大家有没有这个困扰,在 ORM 表达式使用 DateTime.Now.ToString("yyyyMM") 是件很难转换的事,在我适配的这些数据库中,只有 MsAccess 可以直接翻译成对应的 SQL 执行。

这个想法来自另一个 ORM issues,我时不时会去了解其他 ORM 优点和缺陷,以便给 FreeSql 做补充。

想法出来之后当于,也就是昨天 2020/5/24 奋战一宿完成的,除了每个数据库进行编码适配外,更多的时间耗在了单元测试上,目前已全部通过(4000+单元测试不是吹的)。

仅以此功能让大家感受一下 FreeSql 的认真,他不是一些人口中所说的个人项目,谢谢。

var dtn = DateTime.Parse("2020-1-1 0:0:0");
var dts = Enumerable.Range(1, 12).Select(a => dtn.AddMonths(a)).Concat(Enumerable.Range(1, 31).Select(a => dtn.AddDays(a))).Concat(Enumerable.Range(1, 24).Select(a => dtn.AddHours(a))).Concat(Enumerable.Range(1, 60).Select(a => dtn.AddMinutes(a))).Concat(Enumerable.Range(1, 60).Select(a => dtn.AddSeconds(a)));
foreach (var dt in dts)
{Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"), fsql.Select<T>().First(a => dt.ToString()));Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss"), fsql.Select<T>().First(a => dt.ToString("yyyy-MM-dd HH:mm:ss")));Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm"), fsql.Select<T>().First(a => dt.ToString("yyyy-MM-dd HH:mm")));Assert.Equal(dt.ToString("yyyy-MM-dd HH"), fsql.Select<T>().First(a => dt.ToString("yyyy-MM-dd HH")));Assert.Equal(dt.ToString("yyyy-MM-dd"), fsql.Select<T>().First(a => dt.ToString("yyyy-MM-dd")));Assert.Equal(dt.ToString("yyyy-MM"), fsql.Select<T>().First(a => dt.ToString("yyyy-MM")));Assert.Equal(dt.ToString("yyyyMMddHHmmss"), fsql.Select<T>().First(a => dt.ToString("yyyyMMddHHmmss")));Assert.Equal(dt.ToString("yyyyMMddHHmm"), fsql.Select<T>().First(a => dt.ToString("yyyyMMddHHmm")));Assert.Equal(dt.ToString("yyyyMMddHH"), fsql.Select<T>().First(a => dt.ToString("yyyyMMddHH")));Assert.Equal(dt.ToString("yyyyMMdd"), fsql.Select<T>().First(a => dt.ToString("yyyyMMdd")));Assert.Equal(dt.ToString("yyyyMM"), fsql.Select<T>().First(a => dt.ToString("yyyyMM")));Assert.Equal(dt.ToString("yyyy"), fsql.Select<T>().First(a => dt.ToString("yyyy")));Assert.Equal(dt.ToString("HH:mm:ss"), fsql.Select<T>().First(a => dt.ToString("HH:mm:ss")));Assert.Equal(dt.ToString("yyyy MM dd HH mm ss yy M d H hh h"), fsql.Select<T>().First(a => dt.ToString("yyyy MM dd HH mm ss yy M d H hh h")));Assert.Equal(dt.ToString("yyyy MM dd HH mm ss yy M d H hh h m s tt t").Replace("上午", "AM").Replace("下午", "PM").Replace("上", "A").Replace("下", "P"), fsql.Select<T>().First(a => dt.ToString("yyyy MM dd HH mm ss yy M d H hh h m s tt t")));
}

支持常用 c# 日期格式化,yyyy MM dd HH mm ss yy M d H hh h m s tt t

tt t 为 AM PM

AM PM 这两个转换不完美,勉强能使用。

7|0IUpdate.SetSourceIgnore 不更新 null 字段

这个功能被用户提了几次,每一次都认为 FreeSql.Repository 的状态对比可以完成这件事。

这一次作者心疼他们了,为什么一定要用某个功能限制住使用者?大家是否经常听谁说 EF框架、MVC框架,框架的定义其实是约束+规范。

作者不想做这样的约束,作者更希望尽量提供多一些实用功能让用户自己选择,把项目定义为:功能组件。

fsql.Update<Song>().SetSourceIgnore(item, col => col == null).ExecuteAffrows();

第二个参数是 Func<object, bool> 类型,col 相当于属性的值,上面的代码更新实体 item 的时候会忽略 == null 的属性。

8|0Ado.net 访问达梦数据库

武汉达梦数据库有限公司成立于2000年,为中国电子信息产业集团(CEC)旗下基础软件企业,专业从事数据库管理系统的研发、销售与服务,同时可为用户提供大数据平台架构咨询、数据技术方案规划、产品部署与实施等服务。多年来,达梦公司始终坚持原始创新、独立研发,目前已掌握数据管理与数据分析领域的核心前沿技术,拥有全部源代码,具有完全自主知识产权。

不知道大家没有听说过相关政策,政府推动国产化以后是趋势,虽然 .NET 不是国产,但是目前无法限制编程语言,当下正在对操作系统、数据库强制推进。

我们知道 EFCore for oracle 问题多,并且现在还没更新到 3.x,在这样的背景下,一个国产数据库更不能指望谁实现好用的 EFCore。目前看来除了 EFCore for sqlserver 我们没把握完全占优势,起码在其他数据库肯定是我们更接地气。

言归正传,达梦数据库其实蛮早就支持了,之前是以 Odbc 的方式实现的,后面根据使用者的反馈 Odbc 环境问题比较麻烦,经研究决定支持 ado.net 适配,让使用者更加方便。使用 ado.net 方式连接达梦只需要修改 IFreeSql 创建时候的类型即可,如下:

static IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.Dameng, connectionString).UseAutoSyncStructure(true) //自动同步实体结构到数据库.Build(); //请务必定义成 Singleton 单例模式

9|0兼容 EFCore 实体特性、FluentApi

EFCore 目前用户量最多,为了方便一些项目过渡到 FreeSql,我们做了一些 “AI”:

  • 自动识别 EFCore 实体特性:Key/Required/NotMapped/Table/Column

[Table("table01")] //这个其实是 EFCore 的特性
class MyTable
{[Key]public int Id { get; set; }
}

与 EFCore 90% 相似的 FluentApi

fsql.CodeFirst.Entity<Song>(eb => {eb.ToTable("tb_song");eb.Ignore(a => a.Field1);eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();eb.Property(a => a.Url).HasMaxLength(100);eb.Property(a => a.RowVersion).IsRowVersion();eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp");eb.HasKey(a => a.Id);eb.HasIndex(a => new { a.Id, a.Title }).IsUnique().HasName("idx_xxx11");//一对多、多对一eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);//多对多eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
});fsql.CodeFirst.Entity<SongType>(eb => {eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);eb.HasData(new[]{new SongType{Id = 1,Name = "流行",Songs = new List<Song>(new[]{new Song{ Title = "真的爱你" },new Song{ Title = "爱你一万年" },})},new SongType{Id = 2,Name = "乡村",Songs = new List<Song>(new[]{new Song{ Title = "乡里乡亲" },})},});
});public class SongType {public int Id { get; set; }public string Name { get; set; }public List<Song> Songs { get; set; }
}
public class Song {[Column(IsIdentity = true)]public int Id { get; set; }public string Title { get; set; }public string Url { get; set; }public DateTime CreateTime { get; set; }public int TypeId { get; set; }public SongType Type { get; set; }public int Field1 { get; set; }public long RowVersion { get; set; }
}

10|0ISelect.ToTreeList 查询树型数据 List

这是几个意思?有做过父子关系的表应该知道的,把数据查回来了是平面的,需要再用递归转化为树型。考虑到这个功能实用性比较高,所以就集成了进来。来自单元测试的一段代码:

var repo = fsql.GetRepository<VM_District_Child>();
repo.DbContextOptions.EnableAddOrUpdateNavigateList = true;
repo.DbContextOptions.NoneParameter = true;
repo.Insert(new VM_District_Child
{Code = "100000",Name = "中国",Childs = new List<VM_District_Child>(new[] {new VM_District_Child{Code = "110000",Name = "北京市",Childs = new List<VM_District_Child>(new[] {new VM_District_Child{ Code="110100", Name = "北京市" },new VM_District_Child{ Code="110101", Name = "东城区" },})}})
});
var t3 = fsql.Select<VM_District_Child>().ToTreeList();
Assert.Single(t3);
Assert.Equal("100000", t3[0].Code);
Assert.Single(t3[0].Childs);
Assert.Equal("110000", t3[0].Childs[0].Code);
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);

注意:实体需要配置父子导航属性

11|0BulkCopy 大批量数据

原先 FreeSql 对批量数据操作就做得还可以,例如批量数据超过数据库某些限制的,会拆分执行,性能其实也还行。

本需求也是来自用户,然后就实现了,实现完了我还专门做了性能测试对比,sqlserver bulkcopy 收益比较大,mysql 收益非常小。

测试结果(52个字段,18W-50行数据,单位ms):

测试结果,是在相同操作系统下进行的,并且都有预热

ExecuteMySqlBulkCopy 方法在 FreeSql.Provider.MySqlConnector 中实现的

12|0Sqlite :memory: 内存模式

了解 EFCore 应该知道有一个 inMemory 实现,Sqlite 其实也有内存模式,所以在非常棒(忍不住)的 FreeSql.Provider.Sqlite 稍加适配就可以实现 inMemory 模式了。

使用 inMemory 模式非常简单,只需要修改 IFreeSql 创建的类型,以及连接字符串即可:

static IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.Sqlite, "Data Source=:memory:").UseAutoSyncStructure(true) //自动同步实体结构到数据库.Build(); //请务必定义成 Singleton 单例模式

内存模式 + FreeSql CodeFirst 功能,用起来体验还是不错的。因为每次都要迁移结构,fsql 释放数据就没了。

13|0终于写完了

终于写完了,这篇文章是我有史以来编辑最长时间的,历时 4小时!!!原本我可以利用这 4小时编写一堆胶水代码,却非要写推广的文章,真心希望正在使用的、善良的您能动一动小手指,把文章转发一下,让更多人知道 .NET 有这样一个好用的 ORM 存在。谢谢了!!

FreeSql 开源协议 MIT https://github.com/dotnetcore/FreeSql,可以商用,文档齐全。QQ开发群:4336577

CSRedisCore 说:FreeSql 的待遇也好太多了。

如果你有好的 ORM 实现想法,欢迎给作者留言讨论,谢谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309658.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MapReduce简述

MapReduce 参考&#xff1a; https://www.cnblogs.com/lixiansheng/p/8942370.html https://baike.baidu.com/item/MapReduce/133425?fraladdin 概念 MapReduce是面向大数据并行处理的计算模型&#xff0c;用于大规模数据集的并行计算。它提供了一个庞大但设计精良的并行计算…

调试实战 —— dll 加载失败之全局变量初始化篇

前言 最近项目里总是遇到 dll 加载不上的问题&#xff0c;原因各种各样。今天先总结一个虽然不是项目中实际遇到的问题&#xff0c;但是却非常经典的问题。其它几种问题&#xff0c;后续慢慢总结。示例代码包含一个 exe 工程&#xff0c;两个 dll 工程。exe 会加载两个 dll 并调…

MongoDB副本集

参考&#xff1a;https://www.cnblogs.com/littleatp/p/8562842.html https://www.cnblogs.com/ilifeilong/p/14347008.html MongoDB副本集 MongoDB副本集是由一组Mongod实例&#xff08;进程&#xff09;组成&#xff0c;包含一个Primary节点和多个Secondary节点。客户端的所…

博客系统知多少:揭秘那些不为人知的学问(一)

点击上方蓝字关注“汪宇杰博客”导语在我们生活的年代&#xff0c;博客并不稀奇&#xff0c;甚至可以说是随处可见。从最早的搜狐、新浪博客&#xff0c;再到每个人都曾记录青春的 QQ 空间&#xff0c;再到现在的 Vlog 与 Plog&#xff0c;似乎拥有一个自己的博客并不是什么难事…

MongoDB 分片

MongoDB 分片 高数据量&#xff08;消耗内存&#xff09;和高吞吐量&#xff08;消耗CPU&#xff09;的数据库应用会对单机的性能造成较大压力&#xff0c;为了解决这些问题&#xff0c;一般采用两种方法&#xff1a;水平扩展&#xff08;将数据集分布在多个服务器上&#xff…

How many ways HDU - 1978(记忆化搜索关于求多少种方式模板)

题目&#xff1a; 这是一个简单的生存游戏&#xff0c;你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m)。游戏的规则描述如下&#xff1a; 1.机器人一开始在棋盘的起始点并有起始点所标有的能量。 2.机器人只能向右或者向下走&#xff0c;并且每走一步消耗一单位…

Sql Server之旅——第七站 复合索引和include索引到底有多大区别?

索引和锁&#xff0c;这两个主题对我们开发工程师来说&#xff0c;非常的重要。。。只有理解了这两个主题&#xff0c;我们才能写出高质量的sql语句&#xff0c;在之前的博客中&#xff0c;我所说的索引都是单列索引。。。当然数据库不可能只认单列索引&#xff0c;还有我这篇的…

掌握了Docker Layer Caching才敢自称精通Dockerfile

长话短说&#xff1a;本次原创将向您展示在Docker中使用Layer Cache以加快镜像构建。“这个话题的初衷在于&#xff1a;应用打包过程是很慢的(下载并安装框架&第三方依赖包、生成assets)&#xff0c;这个过程在Docker中也不能避免。About Layer Caching in DockerDocker使…

How Many Answers Are Wrong HDU - 3038(带权并查集)

题意&#xff1a; TT写一个数列&#xff0c;现在TT会选择一个区间&#xff0c;然后让FF计算这个区间里面所有数的和&#xff0c;FF准备捉弄一下TT&#xff0c;有时候她会故意计算出来一个错的答案&#xff0c;当然TT也比较聪明&#xff0c;他会发现这个答案跟以前的答案会有冲…

ASP.NET Core on K8s学习之旅(14)Ingress灰度发布

【云原生】| 作者/Edison Zhou这是恰童鞋骚年的第236篇原创文章上一篇介绍了Ingress的基本概念和Nginx Ingress的基本配置和使用&#xff0c;然后我还录了一个快速分享小视频介绍了一下蓝绿发布和灰度发布策略的基本概念&#xff0c;本篇介绍一下如何实战使用Nginx Ingress实现…

[汇编语言]实验:应用更灵活的寻址方式来定位内存地址

实验内容: &#xff08;1&#xff09;将datasg段中每个单词的头一个字母改成大写字母。 datasg段中的数据为: &#xff08;2&#xff09; 将datasg段中每个单词的字母改成大写字母。 datasg段中的数据为: ibm dec dos vax …

你需要了解操作系统发展历程

本文我们大概回顾计算机操作系统发展历程&#xff0c;这里不会记录关于操作系统的完整历史记录&#xff0c;只是记录那些里程碑事件&#xff0c;看看各位接触计算机时&#xff0c;操作系统发展正处于哪个年代起初没有操作系统&#xff0c;没有编程语言或编译器&#xff0c;甚至…

基于 abp vNext 和 .NET Core 开发博客项目 - 使用Redis缓存数据

上一篇文章完成了项目的全局异常处理和日志记录。在日志记录中使用的静态方法有人指出写法不是很优雅&#xff0c;遂优化一下上一篇中日志记录的方法&#xff0c;具体操作如下&#xff1a;在.ToolKits层中新建扩展方法Log4NetExtensions.cs。//Log4NetExtensions.cs using log4…

第一讲 工作区和GOPATH

此为 《极客时间&Go语言核心36讲》 个人笔记&#xff0c;具体课程详见极客时间官网。 Table of Contents generated with DocToc 第一讲 工作区和GOPATH 1. 环境变量配置2. 配置GOPATH的意义 2.1 Go语言源码的组织方式2.2 源码安装后的结果&#xff08;归档文件、可执行文…

开发大会上,前微软CEO放出的狠话!.NET开发随时起飞,你准备好了吗?

“开发者&#xff0c;开发者&#xff0c;开发者&#xff0c;开发者”&#xff0c;微软前任CEO史蒂夫鲍尔默(Steve Ballmer)用这种略带疯狂、又唱又跳的方式表达他对开发者的热爱。不夸张的说&#xff0c;相比二十年前那个如日中天的巨无霸微软&#xff0c;现在的微软比以往任何…