[开源] 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 NameVersion
FreeSql.Provider.MySqlNETStandard2.0、net452
FreeSql.Provider.PostgreSQLNETStandard2.0、net45
FreeSql.Provider.SqlServerNETStandard2.0、net451
FreeSql.Provider.SqliteNETStandard2.0、net45
FreeSql.Provider.OracleNETStandard2.0、net45
FreeSql.Extensions.LazyLoadingNETStandard2.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 NameVersion
FreeSql.Provider.MySqlConnectorNETStandard2.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 的生成器项目,界面都做好了如下:

1694977-20190604192205036-1969837238.png

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

1694977-20190604192335268-131877756.png

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

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

结束语

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值