[开源] FreeSql 配套工具,基于 Razor 模板实现最高兼容的生成器
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 驱动。代码如下:
public IFreeSql<TMark> Build<TMark>() {
if (string.IsNullOrEmpty(_masterConnectionString)) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString");
IFreeSql<TMark> ret = null;
Type type = null;
switch(_dataType) {
case DataType.MySql:
type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySql")?.MakeGenericType(typeof(TMark));
if (type == null) type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySqlConnector")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载");
break;
case DataType.SqlServer: type = Type.GetType("FreeSql.SqlServer.SqlServerProvider`1,FreeSql.Provider.SqlServer")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.SqlServer.dll,可前往 nuget 下载");
break;
case DataType.PostgreSQL: type = Type.GetType("FreeSql.PostgreSQL.PostgreSQLProvider`1,FreeSql.Provider.PostgreSQL")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.PostgreSQL.dll,可前往 nuget 下载");
break;
case DataType.Oracle: type = Type.GetType("FreeSql.Oracle.OracleProvider`1,FreeSql.Provider.Oracle")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Oracle.dll,可前往 nuget 下载");
break;
case DataType.Sqlite: type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.Sqlite")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Sqlite.dll,可前往 nuget 下载");
break;
default: throw new Exception("未指定 UseConnectionString");
}
ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString }) as IFreeSql<TMark>;
if (ret != null) {
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower;
ret.CodeFirst.IsSyncStructureToUpper = _isSyncStructureToUpper;
ret.CodeFirst.IsConfigEntityFromDbFirst = _isConfigEntityFromDbFirst;
ret.CodeFirst.IsNoneCommandParameter = _isNoneCommandParameter;
ret.CodeFirst.IsLazyLoading = _isLazyLoading;
var ado = ret.Ado as Internal.CommonProvider.AdoProvider;
ado.AopCommandExecuting += _aopCommandExecuting;
ado.AopCommandExecuted += _aopCommandExecuted;
}
return ret;
}
自定义导航属性关系的配置
FreeSql 原先支持约定式导航关系配置,对于新项目开发无疑可约定,但是很多老项目命名不规范的就使用不了相关的功能。
有关约定配置可参考 github wiki 中心文档
QQ 开发群真是个好平台,在发起讨论后,各位大佬都纷纷提出建议,最后以一票否决了各大建议,哈哈。。
主要从语法和用户使用的感受上设计,还是那个理念:日式简约!不能加入太多特性和功能,增加用户的理解和使用成本。
最终效果如下:
//导航属性,OneToMany
[Navigate("Song_id")]
public virtual List<song_tag> Obj_song_tag { get; set; }
//导航属性,ManyToOne/OneToOne
[Navigate("Song_id")]
public virtual song Obj_song { get; set; }
[Navigate("Tag_id")]
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 模板实现最高兼容的生成器的更多相关文章
- 基于ABP做一个简单的系统——实战篇:4.基于富文本编辑器,Razor模板引擎生成内容并导出Word 填坑记录
起因 需求是这样的,有一种协议需要生成,协议的模板是可配置的,在生成过程中,模板中的内容可以根据约定的标记进行替换(就像mvc的razor模板一样).生成后的内容还需要导出成word或pdf. 常见的 ...
- .NET Core/.NET5/.NET6 开源项目汇总13:模板引擎
系列目录 [已更新最新开发文章,点击查看详细] 开源项目是众多组织与个人分享的组件或项目,作者付出的心血我们是无法体会的,所以首先大家要心存感激.尊重.请严格遵守每个项目的开源协议后再使用.尊 ...
- 【Hades】ades是一个开源库,基于JPA和Spring构建,通过减少开发工作量显著的改进了数据访问层的实现
几乎每个应用系统都需要通过访问数据来完成工作.要想使用领域设计方法,你就需要为实体类定义和构建资源库来实现领域对象的持久化.目前开发人员经常使用JPA来实现持久化库.JPA让持久化变得非常容易,但是仍 ...
- Razor模板引擎
Razor模板引擎 阅读目录 一.简介 二.非Mvc中使用Razor 三.总结 回到目录 一.简介 在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作:在以前我们一般常用的有Raz ...
- [转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction
本文参考自下面文章整理 MVC Razor模板引擎 @RenderBody.@RenderPage.@RenderSection及Html.RenderPartial.Html.RenderActio ...
- 脱离MVC使用Razor模板引擎
关于Razor模板引擎 1.简介 模板引擎:Razor.Nveocity.Vtemplate.Razor有VS自动提示.使用起来会方便一点. 但是Razor大多是在MVC下使用的. 那么如何在非MVC ...
- Razor模板引擎 (RazorEngine)
Razor模板引擎不仅在ASP.NET MVC中内置了Razor模板引擎,还有一个开源的RazorEngine, 这样以来我们可以在非ASP.NET MVC项目中使用Razor引擎,甚至在控制台,Wi ...
- Razor - 模板引擎 / 代码生成 - RazorEngine
目录 Brief Authors Official Website RazorEngine 的原理 - 官方解释 安装记录 Supported Syntax (默认实现支持的语法) 测试记录 - ca ...
- MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式
MVC的验证(模型注解和非侵入式脚本的结合使用) @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...
随机推荐
- [转]自定义UiPath Activity实践
本文转自:https://segmentfault.com/a/1190000017440647 为了对UiPath Activity的实现方式一探究竟,自己尝试实践编写了一个简单的Activity, ...
- InnoDB Architecture (InnoDB In-Memory Structures 转载)
转载.节选于 https://dev.mysql.com/doc/refman/8.0/en/innodb-in-memory-structures.html InnoDB Architecture ...
- XTTS Creates Alias on Destination when Source and Destination use ASM (Doc ID 2351123.1)
XTTS Creates Alias on Destination when Source and Destination use ASM (Doc ID 2351123.1) APPLIES TO: ...
- ORM查询(细致):
ORM查询(细致): 1.正向查找 ret1=model.Book.objects.first() print(ret1.title) print(ret1.price) print(ret1.pub ...
- 用POI 3.17 导出EXECL
代码参考 https://www.cnblogs.com/bmbm/archive/2011/12/08/2342261.html 效果 导入jar包 <dependency> <g ...
- 洛谷 UVA10226 Hardwood Species
洛谷 UVA10226 Hardwood Species 洛谷评测传送门 题目描述 PDF 输入格式 输出格式 输入输出样例 输入 #1复制 输出 #1复制 题目翻译: 给定若干字符串,输出格式为:( ...
- 【问题记录】 Linux分区磁盘占满,导致ssh登陆闪退
问题描述 今天要去后台看日志查个问题,通过ssh登陆到服务器后准备用平时非常熟悉的less命令打开日志查看,突然xshell客户端就闪退了.一时感觉很蒙,怎么回事??由于之前有同事遇到类似的问题,提醒 ...
- PostgreSQL学习之路一
PostgreSQL的扩展PostGIS是最著名的开源GIS数据库. 安装PostgreSQL是第一步. 1.下载PostgreSQL的二进制安装文件 PostgreSQL官网–>Downloa ...
- TypeScript `this` 入参
考察下面的示例代码: class MyClass { constructor(protected foo: string) {} @MyDecorator bar() { console.log(&q ...
- Xcode 中配置 clang-format 格式化 C++ 代码
Xcode 自带的代码格式化功能(control + I)很有限,其 "格式化" 仅限于设置缩进,代码里面的格式是不会处理的.所以需要借助额外的工具来完成代码的美化. clang- ...