FreeSql 经过半年的开发和坚持维护,在 0.6.x 版本中完成了几大重要事件:

1、按小包拆分,每个数据库实现为单独 dll;

2、实现 .net framework 4.5 支持;

3、同时支持 MySql.Data、MySqlConnector 的实现;

4、自定义导航属性关系的配置;

5、配套工具 FreeSql.Tools 发布;

本文主要讲解第5项《FreeSql.Tools》,大主角往往在最后才出现!!!

拆分小包

在此之前一直被吐槽 FreeSql 臃肿,没有小包开发理念。其实我是一点也不承认这种评价,虽然刚开始只有一个 FreeSql.dll,但是在开发和规划上简单了很多。

有一条开发原则这样讲道:过早优化是恶梦!

大概意思是无论做什么项目,不要想着一开始就过度系统的、规范的执行。从外界来看是正规了,但是进度和稳定性会大大折扣。可以不信我,但是请一定要相信前人的总结啊!!!

从之前的一个 dll 到拆分成小包,我们总共耗时两天,虽然都在一个项目内开发,但其实耦合性并不高,so easy!!

车到山前必有路,时机到了自然会拆。这个时机也是奠定 FreeSql 走出了稳定关键的一步。这样会有更多人愿意加入 FreeSql 阵营。

  • 各数据库单独包、延时加载包;
  • FreeSql.Extensions.LazyLoading
  • FreeSql.Provider.MySql
  • FreeSql.Provider.PostgreSQL
  • FreeSql.Provider.SqlServer
  • FreeSql.Provider.Sqlite
  • FreeSql.Provider.Oracle

支持 .netframework 4.5

早期 FreeSql 主要是在 .net core 最方便的 ORM!NETStandard 是新的标准,然而前段时间微软又说 ..net5 将合并。。。变化真的太快。

在实现拆分小包后,其实 FreeSql 的模块更加清淅,并且依赖项非常之少,然后比较容易的做出了 4.5 framework 的适配。

目前支持的版本:

Package Name Version
FreeSql.Provider.MySql NETStandard2.0、net452
FreeSql.Provider.PostgreSQL NETStandard2.0、net45
FreeSql.Provider.SqlServer NETStandard2.0、net451
FreeSql.Provider.Sqlite NETStandard2.0、net45
FreeSql.Provider.Oracle NETStandard2.0、net45
FreeSql.Extensions.LazyLoading NETStandard2.0、net45

MySqlConnector 的实现

mysql 是一个神奇的流行数据库,在 .net 阵营中使用量排名老二。mysql 的版本五花八门,从 5.6 开始有了不同的分支,分支的出现使得 ado.net 驱动不通用。

很多人不推荐使用 MySql.Data 官方驱动,但是 FreeSql 一直在使用官驱,并且支持了所有 5.6 类型,包括 enum/set 等。

然后就有一些人,特别是高手的那些来提出要求,适配一个 MySqlConnector 的实现,然后著名的 A大(茶叔)提了一道 PR ,创建了 FreeSql.Provider.MySqlConnector 项目,99.9999% 源码和原来 FreeSql.Provider.MySql 相同,经过 266 个单元测试后发现,只需要兼容 enum/set 类型,参数化 ? @ 的处理就跑通了。然后就有了现在新的驱动包:

Package Name Version
FreeSql.Provider.MySqlConnector NETStandard2.0、net45

然后 FreeSqlBuilder 使用反射决定使用哪个 mysql 驱动。代码如下:

  1. public IFreeSql<TMark> Build<TMark>() {
  2. if (string.IsNullOrEmpty(_masterConnectionString)) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString");
  3. IFreeSql<TMark> ret = null;
  4. Type type = null;
  5. switch(_dataType) {
  6. case DataType.MySql:
  7. type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySql")?.MakeGenericType(typeof(TMark));
  8. if (type == null) type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySqlConnector")?.MakeGenericType(typeof(TMark));
  9. if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载");
  10. break;
  11. case DataType.SqlServer: type = Type.GetType("FreeSql.SqlServer.SqlServerProvider`1,FreeSql.Provider.SqlServer")?.MakeGenericType(typeof(TMark));
  12. if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.SqlServer.dll,可前往 nuget 下载");
  13. break;
  14. case DataType.PostgreSQL: type = Type.GetType("FreeSql.PostgreSQL.PostgreSQLProvider`1,FreeSql.Provider.PostgreSQL")?.MakeGenericType(typeof(TMark));
  15. if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.PostgreSQL.dll,可前往 nuget 下载");
  16. break;
  17. case DataType.Oracle: type = Type.GetType("FreeSql.Oracle.OracleProvider`1,FreeSql.Provider.Oracle")?.MakeGenericType(typeof(TMark));
  18. if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Oracle.dll,可前往 nuget 下载");
  19. break;
  20. case DataType.Sqlite: type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.Sqlite")?.MakeGenericType(typeof(TMark));
  21. if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Sqlite.dll,可前往 nuget 下载");
  22. break;
  23. default: throw new Exception("未指定 UseConnectionString");
  24. }
  25. ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString }) as IFreeSql<TMark>;
  26. if (ret != null) {
  27. ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
  28. ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower;
  29. ret.CodeFirst.IsSyncStructureToUpper = _isSyncStructureToUpper;
  30. ret.CodeFirst.IsConfigEntityFromDbFirst = _isConfigEntityFromDbFirst;
  31. ret.CodeFirst.IsNoneCommandParameter = _isNoneCommandParameter;
  32. ret.CodeFirst.IsLazyLoading = _isLazyLoading;
  33. var ado = ret.Ado as Internal.CommonProvider.AdoProvider;
  34. ado.AopCommandExecuting += _aopCommandExecuting;
  35. ado.AopCommandExecuted += _aopCommandExecuted;
  36. }
  37. return ret;
  38. }

自定义导航属性关系的配置

FreeSql 原先支持约定式导航关系配置,对于新项目开发无疑可约定,但是很多老项目命名不规范的就使用不了相关的功能。

有关约定配置可参考 github wiki 中心文档

QQ 开发群真是个好平台,在发起讨论后,各位大佬都纷纷提出建议,最后以一票否决了各大建议,哈哈。。

主要从语法和用户使用的感受上设计,还是那个理念:日式简约!不能加入太多特性和功能,增加用户的理解和使用成本。

最终效果如下:

  1. //导航属性,OneToMany
  2. [Navigate("Song_id")]
  3. public virtual List<song_tag> Obj_song_tag { get; set; }
  4. //导航属性,ManyToOne/OneToOne
  5. [Navigate("Song_id")]
  6. public virtual song Obj_song { get; set; }
  7. [Navigate("Tag_id")]
  8. public virtual tag Obj_tag { get; set; }

然后就能使用很多导航的骚操作功能了。

配套工具 FreeSql.Tools 发布(主角压轴)

在此感谢这个工具的作者:mypeng1985,和参考者:movingsam

感谢有你们一帮热心的使用者,帮助 FreeSql 生态添砖加瓦!!

FreeSql 在早期做过一套生成器模板,功能比较隐秘,一般人不知道如何使用。。之后就一直沉迷于 CodeFirst 的功能开发,无法自拔。

然后在10天前,突然感觉 FreeSql 多了好多使用者,这个时间当然需要有从数据库生成实体的需求了!!

Q:没必要搞这种东西了吧 市面上蛮多的,或者搞一套模板完全搞定了?

A:

  • 无法100%类型兼容啊,因为 FreeSql 支持的类型真的很深,然后市场上的类型映射做不到 100% 匹配;

  • 为了挖掘更多功能,生成器还需要有导航属性的支持,这是基本的,因为有导航属性后,FreeSql 操作会骚许多;

本来我发起了一个纯 winform 的生成器项目,界面都做好了如下:

是不是觉得很好看?我觉得好看。。。。其他人觉得丑。我在开发群发给大家看了之后,第二天 FreeSql.Tools 项目就搞出了新的界面,如下:

直接被秒杀了,这是来自作者:mypeng1985 的佳作。

界面看上去非常像 web,但其实不是的,仍然是一个 winform 程序,使用了 html 做界面,c# 做操作功能。

结束语

源码地址:https://github.com/2881099/FreeSql.Tools

FreeSql 从 2018年11月28日立项,开发,到今天 0.6.x,单元测试 1600+,生态也逐渐完善,有得到许多网友的鼓励和支持,感谢你们!感谢参与项目的你们!

[开源] FreeSql 配套工具,基于 Razor 模板实现最高兼容的生成器的更多相关文章

  1. 基于ABP做一个简单的系统——实战篇:4.基于富文本编辑器,Razor模板引擎生成内容并导出Word 填坑记录

    起因 需求是这样的,有一种协议需要生成,协议的模板是可配置的,在生成过程中,模板中的内容可以根据约定的标记进行替换(就像mvc的razor模板一样).生成后的内容还需要导出成word或pdf. 常见的 ...

  2. .NET Core/.NET5/.NET6 开源项目汇总13:模板引擎

    系列目录     [已更新最新开发文章,点击查看详细] 开源项目是众多组织与个人分享的组件或项目,作者付出的心血我们是无法体会的,所以首先大家要心存感激.尊重.请严格遵守每个项目的开源协议后再使用.尊 ...

  3. 【Hades】ades是一个开源库,基于JPA和Spring构建,通过减少开发工作量显著的改进了数据访问层的实现

    几乎每个应用系统都需要通过访问数据来完成工作.要想使用领域设计方法,你就需要为实体类定义和构建资源库来实现领域对象的持久化.目前开发人员经常使用JPA来实现持久化库.JPA让持久化变得非常容易,但是仍 ...

  4. Razor模板引擎

    Razor模板引擎 阅读目录 一.简介 二.非Mvc中使用Razor 三.总结 回到目录 一.简介 在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作:在以前我们一般常用的有Raz ...

  5. [转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction

    本文参考自下面文章整理 MVC Razor模板引擎 @RenderBody.@RenderPage.@RenderSection及Html.RenderPartial.Html.RenderActio ...

  6. 脱离MVC使用Razor模板引擎

    关于Razor模板引擎 1.简介 模板引擎:Razor.Nveocity.Vtemplate.Razor有VS自动提示.使用起来会方便一点. 但是Razor大多是在MVC下使用的. 那么如何在非MVC ...

  7. Razor模板引擎 (RazorEngine)

    Razor模板引擎不仅在ASP.NET MVC中内置了Razor模板引擎,还有一个开源的RazorEngine, 这样以来我们可以在非ASP.NET MVC项目中使用Razor引擎,甚至在控制台,Wi ...

  8. Razor - 模板引擎 / 代码生成 - RazorEngine

    目录 Brief Authors Official Website RazorEngine 的原理 - 官方解释 安装记录 Supported Syntax (默认实现支持的语法) 测试记录 - ca ...

  9. MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式

    MVC的验证(模型注解和非侵入式脚本的结合使用)   @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...

随机推荐

  1. JavaWeb 错误/异常时页面提示

    经常我们会遇到发生页面404错误,服务器 500 异常,如果默认方式处理,则是将异常捕获之后跳到 Tomcat 缺省的异常页面,如下图所示.

  2. diango运行流程

    diango运行流程 Django处理一个请求的流程: 在浏览器的地址栏中输入地址,回车,发了一个GET请求 wsgi模块接收了请求,将请求的相关信息封装成request对象 根据地址找到对应函数 执 ...

  3. office2019专业版激活秘钥 激活码

    office2019专业版激活码 激活秘钥 2019年5月更新 [Key]:F4QWT-NMMKH-XPTV9-W9HFB-B4JCQ [剩余次数:900000+] office2019激活 产品秘钥 ...

  4. Linux & Go & Vscode & 插件

    Linux Deepin 安装Go 安装Go环境 sudo apt-get install golang 验证一下: 输入 $ go env 输出 GOARCH="amd64" G ...

  5. CSharpGL(57)[译]Vulkan清空屏幕

    CSharpGL(57)[译]Vulkan清空屏幕 本文是对(http://ogldev.atspace.co.uk/www/tutorial51/tutorial51.html)的翻译,作为学习Vu ...

  6. IT兄弟连 HTML5教程 HTML5表单 新增的表单属性2

    5  height和width属性 height和width属性规定用于image类型和input标签的图像高度和宽度.图像通常会同时指定高度和宽度属性.如果图像设置高度和宽度,图像所需的空间在加载页 ...

  7. el-dialog模态窗点击空白不消失

    通过查阅ElementUI的官方文档,可以发现Dialog对话框组件提供了一个close-on-click-modal属性来设置el-dialog模态窗点击空白不消失. <el-dialog : ...

  8. Java编程思想——第21章 并发

    前言 对于某些问题,如果能够并行的执行程序中的多个部分,则回变得非常方便甚至必要,这些部分要么看起来是并发执行,要么是在多处理环境下同时执行.并行编辑可以使程序执行速度得到极大提高,或者为设计某些类型 ...

  9. Jenkinsfile构建docker镜像

    pipeline { agent any stages { stage('preparation') { steps { echo "workspace: ${WORKSPACE}" ...

  10. let definitions are not supported by current javascript

    修改为es6即可