年关将至,首页技术含量文章真是越来越少,理解大家盼着放假过年,哥们我何尝不是,先给大家拜个早年。

兄弟我从11月底发了神经,开启了 ORM 功能库的开发之旅,历时两个月编码和文档整理,目前预览版本更新到 v0.0.9 仍是一个初级版本,怎奈今天把 wiki 文档更新到一半,突然想写一篇文章提前向大家介绍项目。

快过年还逼着您来了解新的技术,实在是抱歉了。介绍一下自己,有一些朋友可能知道我本人,我经常会在群里放开源项目,比如 dotnetGen、csredis 等,反感之余仍然希望可以真的帮助到有需要的人,CSRedisCore 正是本人维护的项目,本文介绍的不是它。

简单点介绍,FreeSql 是一个NETStandard ORM 功能库,采用 MIT 开源协议部署在 github。

它实现了的功能特性

  • [x] CodeFirst 迁移。
  • [x] DbFirst 从数据库导入实体类,支持三种模板生成器。
  • [x] 采用 ExpressionTree 高性能读取数据。
  • [x] 类型映射深入支持,比如pgsql的数组类型。
  • [x] 支持丰富的表达式函数。
  • [x] 支持导航属性查询,和延时加载。
  • [x] 支持同步/异步数据库操作方法,丰富多彩的链式查询方法。
  • [x] 支持事务。
  • [x] 支持读写分离。
  • [x] 支持多种数据库,MySql/SqlServer/PostgreSQL/Oracle/Sqlite。

快速开始

var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10";IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, connstr).UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个.UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前(cmd, traceLog) => Console.WriteLine(traceLog)) //监听SQL命令对象,在执行后.UseLogger(null) //使用日志,不指定默认输出控制台 ILogger.UseCache(null) //使用缓存,不指定默认使用内存 IDistributedCache.UseAutoSyncStructure(true) //自动同步实体结构到数据库.UseSyncStructureToLower(true) //转小写同步结构.UseLazyLoading(true) //延时加载导航属性对象,导航属性需要声明 virtual.Build();

定义实体

可从现有数据库生成实体模型,提供 IDbFirst 生成实体模型。或者手动创建模型,基于模型创建或修改数据库,提供 ICodeFirst 同步结构的 API(甚至可以做到开发阶段自动同步)。

[Table(Name = "tb_topic")]
class Topic {[Column(IsIdentity = true, IsPrimary = true)]public int Id { get; set; }public int Clicks { get; set; }public int TestTypeInfoGuid { get; set; }public TestTypeInfo Type { get; set; }public string Title { get; set; }public DateTime CreateTime { get; set; }
}
class TestTypeInfo {public int Guid { get; set; }public int ParentId { get; set; }public TestTypeParentInfo Parent { get; set; }public string Name { get; set; }
}
class TestTypeParentInfo {public int Id { get; set; }public string Name { get; set; }
}ISelect<Topic> select => fsql.Select<Topic>();

查询

普通查询

var sql = select.Where(a => a.Id == 10).ToSql();
///SELECT ... FROM `tb_topic` a WHERE (a.`Id` = 10)sql = select.Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100).ToSql();
///SELECT ... FROM `tb_topic` a WHERE (a.`Id` = 10 AND a.`Id` > 10 OR a.`Clicks` > 100)sql = select.Where(a => new []{1,2,3}.Contains(a.Id)).ToSql();
//SELECT ... FROM `tb_topic` a WHERE (a.`Id` in (1,2,3))

每页20条数据,查询第1页

var sql = select.Page(1, 20).ToSql();
///SELECT ... FROM `tb_topic` a LIMIT 0,20

利用导航属性联表

sql = select.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid).ToSql();
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a__Type.`Guid`, a__Type.`ParentId`, a__Type.`Name`, a.`Title`, a.`CreateTime`
//FROM `tb_topic` a
//LEFT JOIN `TestTypeInfo` a__Type ON a__Type.`Guid` = a.`TestTypeInfoGuid`sql = select.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid).LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId).ToSql();
//SELECT ...
//FROM `tb_topic` a
//LEFT JOIN `TestTypeInfo` a__Type ON a__Type.`Guid` = a.`TestTypeInfoGuid`
//LEFT JOIN `TestTypeParentInfo` a__Type__Parent ON a__Type__Parent.`Id` = a__Type.`ParentId`

子表 Exists 查询

var sql2222 = select.Where(a => select.Where(b => b.Id == a.Id).Any()).ToList();
// SELECT ... FROM `xxx` a WHERE (exists(SELECT 1 FROM `xxx` b WHERE (b.`Id` = a.`Id`)))//两级相同的子表查询
sql2222 = select.Where(a =>select.Where(b => b.Id == a.Id && select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id).Offset(a.Id).Any()).Any()
).ToList();
// SELECT ... FROM `xxx` a WHERE (exists(SELECT 1 FROM `xxx` b WHERE (b.`Id` = a.`Id` AND exists(SELECT 1 FROM `xxx` c WHERE (c.`Id` = b.`Id`) AND (c.`Id` = a.`Id`) AND (c.`Id` = b.`Id`) limit 0,1)) limit 0,1))

查找今天创建的数据

select.Where(a => a.CreateTime.Date == DateTime.Now.Date).ToSql();

支持功能丰富的表达式函数解析,包括(字符串、日期、时间、数学、类型转换)等函数,方便程序员在不了解数据库函数的情况下编写代码。这是非常特色的功能之一,深入细化函数解析尽量做到满意,所支持的类型基础都可以使用对应的表达式函数,例如 日期、字符串、IN查询、数组(PostgreSQL的数组)、字典(PostgreSQL HStore)等等。

获得查询返回的数据

采用 ExpressionTree 优化读取速读,如果懂技术的你一定知道 .NETCore 技术下除了原生代码,最快就是 Emit 和 ExpressionTree。项目在初期使用的反射+缓存,虽然 .NETCore 优化了反射性能,但经过与Dapper性能测试对比之后,发现仍然有一定差距,改成 ExpresstionTree 后才与 Dapper 性能相当。FreeSql 支持的类型较多,现实 ExpressionTree 的复杂度较大,有兴趣的朋友可以翻阅源代码。

返回单条记录

Topic t1 = select.Where(a => a.Id == 1).ToOne();

FreeSql有两个约定,ToOne 永远返回 null 或 有数据的实体对象,ToList 永远返回非 null 的 List<实体类型>

返回 List

List<Topic> t1 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList();

返回 List + 导航属性的数据

List<Topic> t2 = select.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid).ToList();
//此时会返回普通字段 + 导航对象 Type 的数据

指定字段返回

//返回一个字段
List<int> t3 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList(a => a.Id);//返回匿名类
List<匿名类> t4 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList(a => new { a.Id, a.Title });//返回元组
List<(int, string)> t5 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList<(int, string)>("id, title");//返回SQL字段
List<匿名类> t6 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList(a => new {a.Id,a.Title,cstitle = "substr(a.title, 0, 2)", //将 substr(a.title, 0, 2) 作为查询字段csnow = Convert.ToDateTime("now()"), //将 now() 作为查询字段//奇思妙想:怎么查询开窗函数的结果});//返回更为复杂的结构
List<匿名类> t7 = select.From<TestTypeInfo, TestTypeParentInfo>((s, b, c) => s.InnerJoin(a => a.TypeGuid == b.Guid).LeftJoin(a => c.Id == b.ParentId).Where(a => b.Name != "xxx")).ToList((a, b, c) => new {a.Id,a.Title,a.Type,ccc = new { a.Id, a.Title },tp = a.Type,tp2 = new {a.Id,tp2 = a.Type.Name},tp3 = new {a.Id,tp33 = new {a.Id}}});

执行SQL返回数据

class xxx {public int Id { get; set; }public string Path { get; set; }public string Title2 { get; set; }
}List<xxx> t8 = fsql.Ado.Query<xxx>("select * from song");
List<(int, string ,string)> t7 = fsql.Ado.Query<(int, string, string)>("select * from song");
List<dynamic> t9 = fsql.Ado.Query<dynamic>("select * from song");

CodeFirst

支持 CodeFirst 迁移结构至数据库,这应该是(O/RM)必须标配的一个功能。

与其他(O/RM)不同FreeSql支持更多的数据库特性,而不只是支持基础的数据类型,这既是优点也是缺点,优点是充分利用数据库特性辅助开发,缺点是切换数据库变得困难。不同程序员的理念可能不太一致,作为功能库FreeSql支持到了极致,至于是否使用是项目组技术衡量的另一个问题。

尽管多种数据库适配逻辑非常复杂,FreeSql始终秉承优化程序开发习惯的原则尽量去现实,中间碰到了一些非技术无法攻克的难题,比如数据库的自定义类型,和实体类本身就是一种冲突,为了减少使用成本,诸如此类的数据库功能没有得到支持。

除了在实体上标注特性,也支持实体以外配置

fsql.CodeFirst.ConfigEntity<TestFluenttb1>(a => {a.Name("xxdkdkdk1").SelectFilter("a.Id22 > 0");a.Property(b => b.Id).Name("Id22").IsIdentity(true);a.Property(b => b.name).DbType("varchar(100)").IsNullable(true);}).ConfigEntity<TestFluenttb2>(a => {a.Name("xxdkdkdk2").SelectFilter("a.Idx > 0");a.Property(b => b.Id).Name("Id22").IsIdentity(true);a.Property(b => b.name).DbType("varchar(100)").IsNullable(true);});

类型映射

csharp MySql SqlServer PostgreSQL Oracle Sqlite
bool | bool? bit(1) bit bool number(1) boolean
sbyte | sbyte? tinyint(3) smallint int2 number(4) smallint
short | short? smallint(6) smallint int2 number(6) smallint
int | int? int(11) int int4 number(11) integer
long | long? bigint(20) bigint int8 number(21) integer
byte | byte? tinyint(3) unsigned tinyint int2 number(3) int2
ushort | ushort? smallint(5) unsigned int int4 number(5) unsigned
uint | uint? int(10) unsigned bigint int8 number(10) decimal(10,0)
ulong | ulong? bigint(20) unsigned decimal(20,0) numeric(20,0) number(20) decimal(21,0)
double | double? double float float8 float(126) double
float | float? float real float4 float(63) float
decimal | decimal? decimal(10,2) decimal(10,2) numeric(10,2) number(10,2) decimal(10,2)
Guid | Guid? char(36) uniqueidentifier uuid char(36 CHAR) character(36)
TimeSpan | TimeSpan? time time time interval day(2) to second(6) bigint
DateTime | DateTime? datetime datetime timestamp timestamp(6) datetime
DateTimeOffset | DateTimeOffset? - - datetimeoffset timestamp(6) with local time zone -
Enum | Enum? enum int int4 number(16) mediumint
FlagsEnum | FlagsEnum? set bigint int8 number(32) bigint
byte[] varbinary(255) varbinary(255) bytea blob blob
string varchar(255) nvarchar(255) varchar(255) nvarchar2(255) nvarchar(255)
MygisPoint point - - - -
MygisLineString linestring - - - -
MygisPolygon polygon - - - -
MygisMultiPoint multipoint - - - -
MygisMultiLineString multilinestring - - - -
MygisMultiPolygon multipolygon - - - -
BitArray - - varbit(64) - -
NpgsqlPoint - - point - -
NpgsqlLine - - line - -
NpgsqlLSeg - - lseg - -
NpgsqlBox - - box - -
NpgsqlPath - - path - -
NpgsqlPolygon - - polygon - -
NpgsqlCircle - - circle - -
(IPAddress Address, int Subnet) - - cidr - -
IPAddress - - inet - -
PhysicalAddress - - macaddr - -
NpgsqlRange<int> - - int4range - -
NpgsqlRange<long> - - int8range - -
NpgsqlRange<decimal> - - numrange - -
NpgsqlRange<DateTime> - - tsrange - -
PostgisPoint - - geometry - -
PostgisLineString - - geometry - -
PostgisPolygon - - geometry - -
PostgisMultiPoint - - geometry - -
PostgisMultiLineString - - geometry - -
PostgisMultiPolygon - - geometry - -
PostgisGeometry - - geometry - -
PostgisGeometryCollection - - geometry - -
Dictionary<string, string> - - hstore - -
JToken - - jsonb - -
JObject - - jsonb - -
JArray - - jsonb - -
数组 - - 以上所有类型都支持 - -

以上类型和长度是默认值,可手工设置,如 string 属性可指定 [Column(DbType = "varchar(max)")]

DbFirst

FreeSql 同样支持 DbFirst 的开发模式,即先有数据库再有项目,这种传统的开发模式永远不会过时,特别适合老项目仍然在维护,或者数据库重构成本过高的项目。关系型数据库有许多成熟的运维和开发类配套工具,例如我们所关注的ER图工具 PowerdeSigner,使用它可以更直观的查看表之间的关系。除了FreeSql作者同时在维护超过十年的代码生成器dotnetGen项目,它是一款支持超快速开发且高度可控的解决方案,非常喜欢 DbFirst 的开发模式,因此在 FreeSql for DbFirst 功能上会有不错的支持。

DbFirst 模式开发主要提供了不同数据库的表结构查询适配,配合模板生成器现实从数据库导入模型到c#代码中。

生成器是基于 DbFirst 开发的辅助工具,适用老项目一键生成实体。生成器采用模板的方式,实现了三种生成模板:

模板名称 路径 类型映射 外键导航属性 缓存管理 失血 贫血 充血
simple-entity ../Templates/MySql/simple-entity X X X X
simple-entity-navigation-object ../Templates/MySql/simple-entity-navigation-object X X X
rich-entity-navigation-object ../Templates/MySql/rich-entity-navigation-object X X

结语

项目功能与文档较多,许多细节不适合在一篇文章中展示详尽,更多的功能介绍请移步 github wiki 中心。借此文章介绍FreeSql这个国产ORM,希望能得到大家的支持。

FreeSql 口号:打造 .NETCore 最方便的 ORM!

项目地址:https://github.com/2881099/FreeSql

文档中心:https://github.com/2881099/FreeSql/wiki

最后诚心邀请您的参与加入,一起完成 FreeSql 的使命。

转载于:https://www.cnblogs.com/kellynic/p/10310484.html

【纯技术贴】.NETStandard FreeSql v0.0.9 功能预览相关推荐

  1. .NETStandard FreeSql v0.0.9 功能预览

    年关将至,首页技术含量文章真是越来越少,理解大家盼着放假过年,哥们我何尝不是,先给大家拜个早年. 兄弟我从11月底发了神经,开启了 ORM 功能库的开发之旅,历时两个月编码和文档整理,目前预览版本更新 ...

  2. 清华大学计算机科学与技术vlog,院系宣传 | 计算机科学与技术系:会当0绝顶,1览众山小...

    原标题:院系宣传 | 计算机科学与技术系:会当0绝顶,1览众山小 院系概况 南京大学的计算机科学研究起步于1958年.1978年,在原有的计算技术.计算数学.数理逻辑等专业基础上成立了计算机科学系,1 ...

  3. 纯前端下载pdf链接文件,而不是打开预览的解决方案

    纯前端下载pdf链接文件,而不是打开预览的解决方案 参考文章: (1)纯前端下载pdf链接文件,而不是打开预览的解决方案 (2)https://www.cnblogs.com/jackson-yqj/ ...

  4. nacos配置ap_Nacos 1.0.0 功能预览

    本文来自于我的个人主页:Nacos 1.0.0 功能预览,转载请保留链接 ;) Nacos 1.0.0 是正式 GA 的版本,在架构.功能和API设计上进行了全方位的重构和升级,1.0.0版本标志着N ...

  5. pip无法更新_TensorFlow 2.0「开发者预览版」上线,内容每日更新

    TensorFlow 2.0 预览版上线了!近日,谷歌 AI 团队成员 Martin Wicke 在社交网络上向大家发布了这一最流行深度学习框架的「开发者预览版」,该版本又被称为「Nightly 版」 ...

  6. .NET Pet Shop 4.0案例研究预览篇

    概述<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 随着.NE ...

  7. Silverlight 1.0 RC SDK 预览

    微软公司在几周内就会发表Silverlight 1.0 RC版.其实Joe Stegman早已在其博客指出Silverlight 1.0 Beta与Silverlight 1.0 RC版的一些重大差异 ...

  8. 老子学不动系列:Vue 3.0 新特性预览

    尤大昨天在 Vue Toronto 的主题演讲中预览了 Vue 3 .通过利用现代浏览器支持的新功能,Vue 3 将成为我们已经了解和喜爱的Vue.js 的改进版本. 我们期待的 Vue 3 将会是: ...

  9. MT8788 android 9.0 gsensor导致预览与拍出来的照片方向不一致

    在项目中,组装好的样机(主板竖着放)与未组装的主板(水平放置)烧写的同一套代码,经测试发现,组装好的样机(主板竖着放)相机预览与照片方向不一致,未组装的主板(水平放置)相机预览与照片方向是正常的.后来 ...

最新文章

  1. react按需加载(getComponent优美写法),并指定输出模块名称解决缓存(getComponent与chunkFilename)...
  2. 不要痴迷蓝牙耳机了,出门选这个准没错,99W+人的选择
  3. 超酷炫!Facebook用深度学习和弱监督学习绘制全球精准道路图
  4. 玉林财经学校计算机及应用课程,广西玉林财经学校
  5. POJ 3126 Prime Path BFS搜索
  6. 在实际管理中学习管理
  7. pcb过孔与电流对照一览表_PCB设计项目能不能成功,这个因素占了30%
  8. 受限玻尔兹曼机(Restricted Boltzmann Machine)分析
  9. LinuxC高级编程——进程
  10. c语言能让制表符空9个字符码,C语言编程规范 – 嗨!大佟!
  11. 一直跳出来 visual_只练开合跳一个动作,会瘦吗?
  12. OD使用教程7(上)- 调试篇07|解密系列
  13. Web 项目中,MySQL 最新驱动下载、及配置
  14. Word经典技巧大全
  15. 小程序JSAPI预下单与回调
  16. ckfinder的使用及了解config.xml的配置
  17. 中职教计算机专业发展,中等职业教育中计算机专业教育思考
  18. 简洁明了的插值音频重采样算法例子 (附完整C代码)
  19. 信息系统项目管理师(2022年)—— 重点内容:项目人力资源管理(9)
  20. Ubtun16.04 配置baxter机器人

热门文章

  1. K8S删除某一个命名空间下所有的pod deployment statefulset命令
  2. Ansible搭建hadoop3.1.3高可用集群
  3. pythonanywhere使用:进入虚拟机及修改django项目的css样式
  4. 分布式锁的三种实现的对比
  5. 如何理解拜占庭将军问题?
  6. Scala算术运算符细节说明
  7. Linux whoami指令
  8. 请说明一下Spring中BeanFactory和ApplicationContext的区别是什么?
  9. JavaSE、JavaEE与Spring的概念和异同点剖析
  10. lisp 角平分线_最佳VisualLISP及VBAforAutoCAD2000程序123例 张光斌.pdf