.NET ORM FreeSql 第一个正式版本发布 v1.0.0

一、简介

FreeSql 是 .NET 平台下的对象关系映射技术(O/RM),支持 .NetCore 2.1+ 或 .NetFramework 4.0+ 或 Xamarin。

从 0.0.1 发布到今历时整整一年的迭代更新,现在终于敢发布第一个正式版。

本文内容从简,介绍项目的主要功能框架,以及暂时能想到的可能比较有说服力的特性。

二、项目统计

主仓库解决方案共计项目:29个

单元测试:3510个

Code Issues:168个

文档Wiki:43个

Stars:1140

Forks:236

Commits:690次

Nuget主包下载量:86,568次

开源地址:https://github.com/2881099/FreeSql

三、功能结构

支持 CodeFirst 迁移,哪怕使用 Access 数据库也支持;

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

支持 深入的类型映射,比如pgsql的数组类型;

支持 丰富的表达式函数,以及灵活的自定义解析;

支持 导航属性一对多、多对多贪婪加载,以及延时加载;

支持 读写分离、分表分库,租户设计,过滤器,乐观锁,悲观锁;

支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/达梦数据库/Access;

四、CodeFirst/DbFirst

一切皆 CodeFirst,所有功能都是由实体类型,到表操作的过程。CodeFirst 【自动迁移】只需要一行代码:

using FreeSql;

static IFreeSql fsql = new FreeSqlBuilder()

    .UseConnectionString(DataType.Sqlite, 

        @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10")

    .UseAutoSyncStructure(true) //自动同步实体结构到数据库

    .Build();

在开发过程中,表结构会自动创建、或改变(不丢数据),取决于实体类的变化。

CodeFirst 提供功能丰富的特性ColumnAttribute,定义实体与表间的映射,并且支持 FluentApi 方式。如果不喜欢 ColumnAttribute 这个名字,还可以通过 AOP 设置换为 MyColumnAttribute。

using FreeSql.DataAnnotations;

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; }

}

DbFirst 数据表先行,许多哥们使用动软、T4模板生成实体类代码。自已处理每种数据库的字段类型,和 csharp 类型对应,比较麻烦,各大 ORM 可能还不通用。

我们提供命令行工具生成实体类,dotnet-tools,对就是它。。非常好用的工具,没有之一。

C:\Users\28810>dotnet tool install -g freesql.generator

可使用以下命令调用工具: FreeSql.Generator

已成功安装工具“freesql.generator”(版本“1.0.0”)。

C:\Users\28810>freesql.generator

        ____                   ____         __

       / __/  ____ ___  ___   / __/ ___ _  / /

      / _/   / __// -_)/ -_) _\ \  / _ `/ / /

     /_/    /_/   \__/ \__/ /___/  \_, / /_/

                                    /_/

  # Github # https://github.com/2881099/FreeSql v1.0.0

    使用 FreeSql 快速生成数据库的实体类

    更新工具:dotnet tool update -g FreeSql.Generator

  # 快速开始 #

  > FreeSql.Generator -Razor 1 -NameOptions 0,0,0,0 -NameSpace MyProject -DB "MySql,Data Source=127.0.0.1;..."

     -Razor 1                  * 选择模板:实体类+特性

     -Razor 2                  * 选择模板:实体类+特性+导航属性

     -Razor "d:\diy.cshtml"    * 自定义模板文件

     -NameOptions              * 总共4个布尔值,分别对应:

                               # 首字母大写

                               # 首字母大写,其他小写

                               # 全部小写

                               # 下划线转驼峰

     -NameSpace                * 命名空间

     -DB "MySql,Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=数据库;Charset=utf8;SslMode=none;Max pool size=2"

     -DB "SqlServer,Data Source=.;Integrated Security=True;Initial Catalog=数据库;Pooling=true;Max Pool Size=2"

     -DB "PostgreSQL,Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=数据库;Pooling=true;Maximum Pool Size=2"

     -DB "Oracle,user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2"

     -DB "OdbcDameng,Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789;Max pool size=2"

                               OdbcDameng 是国产达梦数据库,需要使用 ODBC 连接

     -Filter                   Table+View+StoreProcedure

                               默认生成:表+视图+存储过程

                               如果不想生成视图和存储过程 -Fitler View+StoreProcedure

     -FileName                 文件名,默认:{name}.cs

     -Output                   保存路径,默认为当前 shell 所在目录

                               推荐在实体类目录创建 gen.bat,双击它重新所有实体类

它基于 Razor 模板生成,支持自定义模板生成,意味着它远不止可以生成实体类,甚至是 IRepository 或者。。。

五、导航属性

从一开始就着重导航对象的设计,支持一对多、多对多、父子关系、一对一、多对一,不夸张的说目前对导航属性处理最流弊,最容易上手的 ORM。在多表查询的表达式使用上非常便利,如下:

fsql.Select<Catetory>()

    .Where(a => a.Parent.Parent.Name == "粤语")

可以使用导航属性一直这样点下去。。。

级联保存,级联查询功能也必不可少,如下查询多对多:

fsql.Select<Song>()

    .IncludeMany(a => a.Tags)

    .ToList();

上面的代码,如果只返回 Tags 前 5条记录,也是支持的 .IncludeMany(a => a.Tags.Take(5))

对性能有追求,还可以指定 Tags 只查询部分字段

关于 IncludeMany 不便再这过多展开介绍。。。(其实还有黑科技!)

哦,还有 FreeSql.AdminLTE 扩展包,它不属于主仓库项目,最大化利用导航属性完成通用的 CURD 后台管理功能。

流弊哒哒~~~~

六、仓储模式

仓储工作单元目前是当下的流行风,在比较早的时候大约0.2版本发布了第一个仓储版本,当时参考了大量的项目设计,最终选用 abp vnext 的 IRepository 设计接口,实现通用仓储类功能。

也就是说,使用 FreeSql.Repository 你不必再自己写那些繁琐的 CURD 重复的仓储功能,不用再头疼仓储类的接口方法定义。定义标准比写代码难多了,abp vnext 的 IRepository 目前是见过最好的,木有之一!!

仓储模式都在操作实体对象,无论是更新还是删除,都是传对象。。。传传传。。。

问题1、传对象更新,意味着更新所有字段?

不会的,我们的仓储实现拥有状态管理机制,从对象查询出来的时候已经记录了拍照,当调用更新方法的时候会与之对比,计算出变化的字段,只更新变化的字段!

var repo = fsql.GetRepository<Song>();

var item = repo.Where(a => a.Id == 1).First();

item.Title = "原谅我今天";

repo.Update(item);

提示:支持乐观锁、悲观锁

问题2、状态管理是否影响性能?

不完全,因为状态管理设计在仓储实现之上,我们最原始的 IFreeSql 没有这个功能(仓储算是一种扩展包吧,但是仓储又非常有效)。仓储即用即销毁,擅用它的对比功能更新对象,不滥用没有性能问题。

有了仓储怎么会没有 UnitOfWork 呢,UnitOfWork 目前以事务的方式做了默认实现,并且它拥有实体变化跟踪记录。

七、性能

1、插入测试(52个字段)

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

18W 解释:插入18万行记录,表格中的数字是执行时间(单位ms)

Oracle 插入性能不用怀疑,可能安装学生版限制较大

提醒:开源数据库测试结果比较有意义,商业数据库版本之间性能可能有较大差距

2、插入测试(10个字段)

 

提示:已经支持了 SqlServer 数据库的 SqlBulkCopy 功能、以及 PostgreSQL 数据库的 Copy 功能

八、拉姆达

非常特色的功能之一,深入细化函数解析,所支持的类型基本都可以使用对应的表达式函数,例如 日期、字符串、IN查询、数组(PostgreSQL的数组)、字典(PostgreSQL HStore)等等。

1、In查询

var t1 = fsql.Select<T>()

  .Where(a => new[] { 1, 2, 3 }.Contains(a.Id))

  .ToSql();

//SELECT .. FROM ..

//WHERE (a.`Id` in (1,2,3))

已优化,防止 where in 元素多过的 SQL 错误,如:

[Err] ORA-01795: maximum number of expressions in a list a 1000

原来:where id in (1…1333)

现在:where id in (1…500) or id in (501…1000) or id in (1001…1333)

2、In查询(多列)

//元组集合

vae lst = new List<(Guid, DateTime)>();

lst.Add((Guid.NewGuid(), DateTime.Now));

lst.Add((Guid.NewGuid(), DateTime.Now));

lst.Add((Guid.NewGuid(), DateTime.Now));

fsql.Select<T>()

  .Where(a => lst.Contains(a.Id, a.ct1))

  .ToSql();

//SELECT .. FROM ..

//WHERE (a."Id" = '685ee1f6-bdf6-4719-a291-c709b8a1378f' AND a."ct1" = '2019-12-07 23:55:27' OR 

//a."Id" = '5ecd838a-06a0-4c81-be43-1e77633b7404' AND a."ct1" = '2019-12-07 23:55:27' OR 

//a."Id" = 'b8b366f3-1c03-4547-9c96-d362dd5cae6a' AND a."ct1" = '2019-12-07 23:55:27')

3、自定义函数

默认已经支持了很丰富的函数解析,如果不够再自己定义:

[ExpressionCall]

public static class DbFunc

{

    //必要定义 static + ThreadLocal

    static ThreadLocal<ExpressionCallContext> context = new ThreadLocal<ExpressionCallContext>();

    public static DateTime FormatDateTime(this DateTime that, string arg1)

    {

        var up = context.Value;

        if (up.DataType == FreeSql.DataType.Sqlite) //重写内容

            context.Value.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";

        return that;

    }

}

fsql.Select<T>().ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd"));

//SELECT date_format(a."CreateTime", 'yyyy-MM-dd') as1 

//FROM "T" a

提示:SqlServer nvarchar/varchar 已兼容表达式解析,分别解析为:N’’ 和 ‘’,优化索引执行计划

九、骚操作

1、代码注释 -> 迁移到数据库

CodeFirst 支持将 c# 代码内的注释,迁移至数据库的备注。先决条件:

实体类所在程序集,需要开启 xml 文档功能;

xml 文件必须与程序集同目录,且文件名:xxx.dll -> xxx.xml;

2、NoneParameter

可以设置不使用 参数化 执行 SQL 命令,方便开发调试,区别如下:

INSERT INTO `tb_topic`(`Title`) VALUES(?Title0)

INSERT INTO `tb_topic`(`Title`) VALUES('Title_1')

在 new FreeSqlBuilder().UseNoneParameter(true) 全局设置

在 单次 ISelect、IInsert、IDelete、IUpdate 上使用 NoneParameter() 设置单次生效

3、Dto 映射查询

用过 ProjectTo 功能吗?没用过当忽略此行。。。

有些朋友可能是先 ToList().Mapper<T>(),这样会先查询了所有字段。

Dto 映射查询支持单表/多表,这个功能可以决定只查询部分字段(不是、不是、不是先查询所有字段再到内存映射)。

规则:查找属性名,会循环内部对象 _tables(多表会增长),以 主表优先查,直到查到相同的字段。

如:A, B, C 都有 id,Dto { id, a1, a2, b1, b2 },A.id 被映射。也可以指定 id = C.id 映射。

fsql.Select<Song>().ToList(a => new DTO { xxx = a.ext }) 

//情况1:附加所有映射,再额外映射 ext,返回 List<DTO>

fsql.Select<Song>().ToList(a => new Song { id = a.id }) 

//情况2:只查询 id,返回 List<Song>

fsql.Select<Song>().ToList(a => new { id = a.id }) 

//情况3:只查询 id,返回 List<匿名对象>

fsql.Select<Song>().ToList(a => new DTO(a.id))

//情况4:只查询 id,返回 List<DTO>

fsql.Select<Song>().ToList(a => new DTO(a.id) { xxx = a.ext })

//情况5:查询 id, ext,返回 List<DTO>

fsql.Select<Song>().ToList(a => new Song(a.id))

//情况6:查询 id,返回 List<Song>

fsql.Select<Song>().ToList(a => new Song(a.id) { xxx = a.ext })

//情况7:查询 id, ext,返回 List<Song>

4、WhereCascade

FreeSql 擅长多表查询,遇到像isdeleted每个表都给条件的时候,挺麻烦。WhereCascade使用后生成sql时,所有表都附上这个条件。

如:

fsql.Select<t1>()

    .LeftJoin<t2>(...)

    .WhereCascade(x => x.IsDeleted == false)

    .ToList();

得到的 SQL:

SELECT ...

FROM t1

LEFT JOIN t2 on ... AND (t2.IsDeleted = 0) 

WHERE t1.IsDeleted = 0

其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。

5、审计 CURD

如果因为某个 sql 骚操作耗时很高,没有一个相关的审计功能,排查起来可以说无从下手。

FreeSql 支持简单的类似功能:

fsql.Aop.CurdAfter = (s, e) => {

if (e.ElapsedMilliseconds > 200) {

//记录日志

//发送短信给负责人

}

};

只需要一个事件,就可以对全局起到作用。

还有一个 CurdBefore 在执行 sql 之前触发,常用于记录日志或开发调试。

6、审计属性值

实现插入/更新时统一处理某些值,比如某属性的雪花算法值、创建时间值、甚至是业务值。

fsql.Aop.AuditValue += (s, e) => {

    if (e.Column.CsType == typeof(long) 

        && e.Property.GetCustomAttribute<SnowflakeAttribute>(false) != null

        && e.Value?.ToString() == 0)

        e.Value = new Snowflake().GetId();

};

class Order {

    [Snowflake]

    public long Id { get; set; }

    //...

}

当属性的类型是 long,并且标记了 [Snowflake],并且当前值是 0,那么在插入/更新时它的值将设置为雪花id值。

说明:SnowflakeAttribute 是使用者您来定义,new Snowflake().GetId() 也是由使用者您来实现

如果命名规范,可以在 aop 里判断,if (e.Property.Name == “createtime”) e.Value = DateTime.Now;

还有。。还有很多骚操作。。不便在此展开。。。

十、展望 2020

2019 年支持了主流的数据库:

SqlServer 2000-2019,支持 row_number/offset fetch next 分页自动版本选择适配,以及其他语法的差异适配,提供 ado.net 与 odbc 两种实现方式;

PostgreSQL 9.4-12,完成了版本间部分差异适配,提供 ado.net 与 odbc 两种实现方式;

MySql 5.5、Mariadb,提供 Oracle 官方驱动、与 MySqlConnector 社区驱动,还有 odbc 实现方式;

Oracle 11+,提供 ado.net 与 odbc 两种实现方式;

Sqlite,兼容了 .net core / .net framework / xamarin 平台适配,支持 CodeFirst 开发模式,一个字爽!!!

MsAccess 2003-2007,提供 oledb 实现方式,支持 CodeFirst 开发模式;

达梦,提供 odbc 的实现方式,并且支持 DbFirst 和 CodeFirst 两种开发模式;

2020 年支持国产是重点,重心,重要的工作内容,南大通用将是下一个目标,并且已经在进行中了。

开源地址:https://github.com/2881099/FreeSql

写到最后面,感谢这一年来与 FreeSql 一直陪伴的兄弟朋友们。

原文链接:https://blog.csdn.net/dotnetCore/article/details/103704647

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

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

相关文章

Windows上搭建EMQTT服务器

1.官网下载EMQ 2.复制如图文件路径 3.打开终端cmd&#xff0c;输入&#xff1a; 再输入&#xff1a; 4.打开浏览器&#xff0c;进入&#xff1a;http://192.168.1.25:18083/* (localhost可打开终端输入ipconfig查看) 用户名&#xff1a;admin 密码&#xff1a;public

.NET解所有相机RAW格式照片

再聊.NET解相机RAW格式照片上次我发了一篇文章《用.NET解索尼相机ARW格式照片》&#xff0c;提到通过安装 SonyRawFileDecoder的方式&#xff0c;然后调用 WindowsImagingComponents来解析 RAW格式文件。后来我经过进一步研究、探索&#xff0c;发现还有更简单的办法。新的方法…

AspNetCore结合Redis实践消息队列

这是年中首发在博客园上的文章&#xff0c;个人觉得是AspNetCore结合Redis做的一次比较优秀的消息队列重构&#xff0c;其中对于点对点/发布-订阅的思路应该也是面试必考题。引言.Net TPL Dataflow是一个进程内数据流管道&#xff0c;应对高并发、低延迟的要求非常有效&#xf…

提升Azure App Service的几个建议

本文介绍了6个技巧&#xff0c;这些技巧可以改善Azure App Service托管应用程序的性能。其中一些技巧是你现在就可以进行的配置变更&#xff0c;而其他技巧则可能需要对应用程序进行一些重新设计和重构&#xff0c; 本文的几个技巧对于常规企业部署依旧有指引作用。长话短说开发…

单向链表的逆转(数据结构)(c语言)

逆转单向链表的意思是&#xff1a;给定你一个单向链表&#xff0c;一个整数n&#xff08;n为要逆转的结点数&#xff09;&#xff0c;要求你把链表从头结点到第n个结点给逆转过来 图示&#xff1a; 给出一个单向链表&#xff0c;一个整数n4。也就是要求把该链表从头结点&#x…

广东职业教育信息化研究会2019年会暨区块链专题研讨会

兹定于2019年12月28日&#xff08;星期六&#xff09;上午9:30召开广东职业教育信息化研究会2019年会暨专题研讨会&#xff0c;本次会议由广东职业教育信息化研究会主办&#xff0c;华南师范大学网络教育学院协办。会议地址&#xff1a;广州市天河区中山大道西55号华南师范大学…

如何快速融入一个团队?

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一我们难免需要离开一个圈子&#xff0c;加入一个陌生的集体。毋庸置疑&#xff0c;离开熟知的圈子&#xff0c;走向未知的圈子难免会产生许多畏惧甚至情怯&#xff0c;这都…

关于C#异步编程你应该了解的几点建议

前段时间写了一篇关于C#异步编程入门的文章&#xff0c;你可以点击《C#异步编程入门看这篇就够了》查看。这篇文章我们来讨论下关于C#异步编程几个不成文的建议&#xff0c;希望对你写出高性能的异步编程代码有所帮助。注&#xff1a;本文的很多内容都是学习《Effective C#》的…

数据库分区

一、分区原理分区并不是生成新的数据表&#xff0c;而是将表的数据均衡分摊到不同的硬盘&#xff0c;系统或是不同服务器存储介子中&#xff0c;实际上还是一张表。要实现这一功能&#xff0c;首先要了解数据库对水平分区表进行分区存储的原理。数据库分区和分表相似&#xff0…

如何在 C# 平台调用云开发?

▌关于作者苏震巍&#xff0c;云开发Linker计划成员&#xff0c;《微信开发深度解析》作者、Senparc.Weixin 微信 SDK 作者、微软最有价值专家&#xff08;MVP&#xff09;、盛派网络创始人兼首席架构师、微软 Ignite 技术大会讲师、从事软件及互联网研发已有26年&#xff0c;发…

如何打造组织级敏捷,你想知道的都在这里!

“敏捷是适应和响应变化的能力……敏捷组织将变化视为机遇&#xff0c;而不是威胁。” — Jim Highsmith注&#xff1a;Highsmith 在软件开发和 IT 行业有着超过 30 年的经验&#xff0c;曾是敏捷宣言的签署人之一&#xff0c;敏捷联盟的发起人和第一任理事&#xff0c;在很多行…

Azure DevOps Server CI - 自搭跨平台容器代理Agents

前言最近在地端(On-premises)幫團隊搭一套CI/CD流程&#xff0c;也順帶整理了一下從無到有的搭建過程&#xff0c;這次使用了docker技術來解決現有團隊使用CI/CD時讓現有CI/CD hosting環境過於複雜的問題。在開始之前&#xff0c;我先預備一下搭建的環境&#xff0c;如下:Windo…

.Net Core 认证组件源码解析

不知不觉.Net Core已经推出到3.1了,大多数以.Net为技术栈的公司也开始逐步的切换到了Core,从业也快3年多了,一直坚持着.不管环境怎么变,坚持自己的当初的选择,坚持信仰 .Net Core是个非常优秀的框架,如果各位是从WebForm开始,一步步走到今天,自然而然就会发现.微软慢慢的开始将…

在.NET Core下的机器学习--学习笔记

摘要.NET Core 在机器学习的应用场景&#xff0c;除了 ML .NET 还会介绍一个非常棒的開源技術 TensorFlow .NET &#xff0c; Keras .NET.讲师介绍本课内容人工智能介绍ML .NETICSharpCoreTensorFlow .NETKeras .NETSciSharp人工智能应用图像识别/物体识别自然语言/翻译搜索/知…

asp.net core 自定义基于 HttpContext 的 Serilog Enricher

asp.net core 自定义基于 HttpContext 的 Serilog EnricherIntro通过 HttpContext 我们可以拿到很多有用的信息&#xff0c;比如 Path/QueryString/RequestHeader 等请求信息, StatusCode/ResponseHeader 等响应信息&#xff0c;借助 HttpContext 我们可以在日志中记录很多有用…

我的 .NET Core 博客性能优化经验总结

点击上方蓝字关注“汪宇杰博客”导语去年8月&#xff0c;我用 .NET Core 重写了我的博客系统。经过一年多的优化&#xff0c;服务器响应速度从上线时候的 80ms 提高到了现在的 8ms&#xff0c;十倍提速。可惜由于部署在国外&#xff0c;自然不可抗力会导致中国用户晚上访问速度…

Redis 6 RC1发布,带来众多新特性

Redis 6 RC1 发布了&#xff0c;项目创建人 antirez 在博客中介绍&#xff0c;这是迄今最“企业”化的版本&#xff08;SSL 与 ACL 等特性与企业极相关&#xff09;&#xff0c;也是最大的版本&#xff0c;同时也是参与人数最多的版本。GA 版本预计在明年三月到五月之间发布。R…

Serverless那么火,2019年的采用如何?

传统的 IT 架构已经不适合当今快速发展的数字经济环境。技术顾问 Declan Morris 表示&#xff1a;“客户不仅期望零停机时间&#xff0c;而且要求应用程序无论在世界任何地方都具有一致的性能。”他还预测到&#xff0c;接下来是 Serverless 计算和函数即服务&#xff08;FaaS&…

【C】Natasha 插件编程

文章转载授权级别&#xff1a;CNatasha 是一个代替 Emit / Expression 的动态构建项目&#xff0c;旨在为开发者提供方便、快捷、高性能的动态构建服务&#xff0c;动态编程是生态的重要组成部分&#xff0c;希望开发者们能有足够的兴趣来了解、使用、建设它。1、插件生成使用 …

二叉树先序,中序,后序,层次遍历(数据结构)

先序遍历 先序遍历可以想象为&#xff0c;一个小人从一棵二叉树的根节点为起点&#xff0c;沿着二叉树的外沿&#xff0c;逆时针走一圈回到根节点&#xff0c;路上遇到的元素顺序&#xff0c;就是先序遍历的结果 先序遍历的结果为&#xff1a;A B D H I E J C F K G 中序遍…