[开源] 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的验证,包括前台客 ...
随机推荐
- 升鲜宝V2.0_杭州生鲜配送行业,升鲜宝供应链B端订货系统使用说明_升鲜宝生鲜供应链管理系统_15382353715_余东升
升鲜宝V2.0_杭州生鲜配送行业,升鲜宝供应链B端订货系统使用说明_升鲜宝生鲜供应链管理系统_15382353715 升鲜宝生鲜配送供应链系统经过这些年的发展,形成一套独特的订 ...
- SAP用户角色分配函数权限
事务码 PFCG修改角色 选择[权限缺省] 选择 RFC 输入的函数只能是允许远程连接的函数,否则不能调用和添加到角色. 完成添加.
- phpstudy漏洞检测
后门检测脚本 # !/usr/bin/env python # -*- coding:utf-8 -*- import gevent from gevent import monkey gevent. ...
- Spring Boot Mybatis 最基本使用mysql存储过程
首先声明:只是用最简单的方法大致了解如何用存储过程开发,如果需要查看存储过程创建语法的自行百度搜索 一.首先创建最基本的数据库 CREATE TABLE `t_user` ( `id` varchar ...
- ORA-27090: Unable to reserve kernel resources for asynchronous disk I/O
2019-08-19T09:27:33.225584+08:00Slave encountered ORA-27090 exception during crash recoveryRecovery ...
- SQL Server如何通过Page_ID找到对应的表
其实本篇文章算是翻译Finding a table name from a page ID这篇文章,只是不想直接翻译.用自己的理解叙说出来.算是对上一篇博客"SQL Server如何找出一个 ...
- vue-property-decorator和typescript结合构建的class类组件,父组件触发子组件方法的方式
vue-property-decorator和typescript结合构建的class类组件,父组件触发子组件方法的方式 class类组件示例 Father类组件 <template> & ...
- C语言程序设计100例之(15):除法算式
例15 除法算式 问题描述 输入正整数n(2≤n≤68),按从小到大输出所有形如abcde/fghi=n的表达式.其中a~i为1~9的一个排列. 输入格式 每行为一个正整数n (n <= 1 ...
- windows7使用vhd虚拟磁盘
操作系统 : windows7_x64 创建vhd 磁盘管理 --> 操作 --> 创建vhd 挂载vhd 脚本: rem 挂载VHD @echo off (echo select vdi ...
- Vue的MVVM框架理解
图示 只上图,请不要怪楼主懒. 这是楼主梳理后画的,因为毕竟自己画的印象深刻,更觉得香啊. 黄线: 表示View->Model, 红线: 表示Model->View 具体代码,请查看Vue ...