FreeSql.Generator命令行代码生成器是如何实现的
目录
- FreeSql介绍
- FreeSql.Generator
- RazorEngine.NetCore
- 源码解析
- FreeSql.Tools
FreeSql
FreeSql 是功能强大的对象关系映射技术(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.0+ 或 Xamarin。
有一个强大的ORM,也方便我们开发一个代码生成器。
一般情况下,我们开发数据库相关的应用,主要分为三种code first、db first、model first
我只用过前二种,
- code first,代码优先,数据库都是根据实体类生成,所有的关系,可以是逻辑关联,也可以是物理关联。
- DB First: 数据库优先,直接设计表结构,用设计工具生成表,设计主键,外键、索引,关联关系等。
当我们使用DB First时,设计好的数据库,我们怎么生成一些实体类、通用的代码、控制器、服务层、Dto呢。今天我来给大家介绍一下FreeSql项目中的一些工具。当然,不使用此ORM的小伙伴也能使用此工具,因为他是通用。
FreeSql.Generator 命令行方式
通过几行命令,就可实现生成项目中通用的代码结构,不需要复制一段代码后修改,加快开发速度,减少重复劳动,少用一根头发。
由于每个人的项目结构,代码位置各不相同,对于ORM来说,不同的业务逻辑各不相同,所以该项目没有相应的模板,相信使用过Razor的同学一定能实现自己的模板。
1-2年前,我和一个学长也写过代码生成器,这里分享一下当时做项目时的一些模板,https://github.com/i542873057/SJNScaffolding/tree/master/SJNScaffolding.RazorPage/Templates,该项目是基于 . NET Core+Razor Page,由于已离职,所以没有继续维护,这些模板都和ABP相关,当时提取了一些通用的功能,单表操作,可以直接生成前后端功能,只需要在word中按统一的格式写好数据字典的文档,直接复制到系统,即可根据空格,定义类型等方式解析字段。
回到FreeSql.Generator 命令行
- 对于此工具的使用可参考 https://github.com/dotnetcore/FreeSql/wiki/DbFirst
- 源码位置 https://github.com/dotnetcore/FreeSql/tree/master/Extensions/FreeSql.Generator
- 前提是本地安装了.net core 3.1 的sdk.
怎么使用呢。
- 安装 dotnet-tool 生成实体类
dotnet tool install -g FreeSql.Generator
- 新建目录,在地址栏输入 cmd 快速打开命令窗口,输入命令:
FreeSql.Generator --help
我们可以看到
C:\Users\igeekfan\Desktop\code>FreeSql.Generator --help
____ ____ __
/ __/ ____ ___ ___ / __/ ___ _ / /
/ _/ / __// -_)/ -_) _\ \ / _ `/ / /
/_/ /_/ \__/ \__/ /___/ \_, / /_/
/_/
# Github # https://github.com/2881099/FreeSql v1.5.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 "Sqlite,Data Source=document.db"
-DB "Dameng,server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=2"
Dameng 是国产达梦数据库
-Filter Table+View+StoreProcedure
默认生成:表+视图+存储过程
如果不想生成视图和存储过程 -Filter View+StoreProcedure
-Match 正则表达式,只生成匹配的表,如:dbo\.TB_.+
-FileName 文件名,默认:{name}.cs
-Output 保存路径,默认为当前 shell 所在目录
推荐在实体类目录创建 gen.bat,双击它重新所有实体类
- 更新命令行
dotnet tool update -g FreeSql.Generator
- 这里lin-cms-dotnetcore这个项目来测试。
- 数据库表名是下划线,字段也是下划线方式。
- -Razor 指定 第一个模板
- -NameOptions 0,0,0,1 最后一个1,代表 下划线转驼峰,满足C#命名规则
- -NameSpace 指定了命名空间 LinCms.Core.Entities
- -DB 就是数据库的相关配置
- mysql 本地地址 127.0.0.1 3306端口 用户名 root 密码123456 数据库 lin-cms
- -Match book 这样就能只生成book,支持正则表达式,如 -Math lin_user 就会生成以lin_user开头的表。如dbo.TB_.+,会生成以TB开头的表。即只生成匹配的表
- 执行此命令。
FreeSql.Generator -Razor 1 -NameOptions 0,0,0,1 -NameSpace LinCms.Core.Entities -DB "MySql,Data Source=127.0.0.1;Port=3306;User ID=root;Password=123456;Initial Catalog=lincms;Charset=utf8;SslMode=none;Max pool size=2"
这时候代码已经生成了
其中一个代码 生成如下。这些类是partial ,熟悉C#的同学,应该知道,类的定义使用此关键字,我们能在不同的地方为该类扩展。以防止重新同步数据库的结构时,丢失改动的字段。
namespace LinCms.Core.Entities {
[JsonObject(MemberSerialization.OptIn), Table(Name = "book")]
public partial class Book {
/// <summary>
/// 主键Id
/// </summary>
[JsonProperty, Column(Name = "id", IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
[JsonProperty, Column(Name = "author", DbType = "varchar(20)")]
public string Author { get; set; } = string.Empty;
[JsonProperty, Column(Name = "image", DbType = "varchar(50)")]
public string Image { get; set; } = string.Empty;
//更多xxx
}
}
- 最终效果图如下
此时会生成二个文件
__重新生成.bat,下次重新点击他就能重新生成实体类了。
FreeSql.Generator -Razor "__razor.cshtml.txt" -NameOptions 1,1,0,1 -NameSpace MyProject -DB "MySql,Data Source=127.0.0.1;Port=3306;User ID=root;Password=123456;Initial Catalog=lincms;Charset=utf8;SslMode=none;Max pool size=2" -FileName "{name}.cs"
上面的命令-Razor 指定了这个txt文件 __razor.cshtml.txt
我们可以定义自己的模板,以生成符合自已业务的的代码,从而实现快速开发。
我们可以看下模板中的文件内容,他就是asp.net下的mvc 结构下的razor后端模板渲染,把这个.txt后缀去掉,就很明了了。对于asp.net mvc的razor,我们可以将控制器下方法的值替换掉cshtml中的值。这个过程是有一个类库在帮我们实现的,叫RazorEngine,不过那个是.net framework下的实践。.NET Framework 下的RazorEngine代码生成介绍
@using FreeSql.DatabaseModel;@{
var gen = Model as RazorModel;
Func<string, string> GetAttributeString = attr => {
if (string.IsNullOrEmpty(attr)) return null;
return string.Concat(", ", attr.Trim('[', ']'));
};
Func<DbColumnInfo, string> GetDefaultValue = col => {
if (col.CsType == typeof(string)) return " = string.Empty;";
return "";
};
}
//xxx
namespace @gen.NameSpace {
@if (string.IsNullOrEmpty(gen.table.Comment) == false) {
@:/// <summary>
@:/// @gen.table.Comment.Replace("\r\n", "\n").Replace("\n", "\r\n /// ")
@:/// </summary>
}
[JsonObject(MemberSerialization.OptIn)@GetAttributeString(gen.GetTableAttribute())]
public partial class @gen.GetCsName(gen.FullTableName) {
@foreach (var col in gen.columns) {
if (string.IsNullOrEmpty(col.Coment) == false) {
@:/// <summary>
@:/// @col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n /// ")
@:/// </summary>
}
@:@("[JsonProperty" + GetAttributeString(gen.GetColumnAttribute(col)) + "]")
@:public @gen.GetCsType(col) @gen.GetCsName(col.Name) { get; set; }@GetDefaultValue(col)
@:
}
}
@gen.GetMySqlEnumSetDefine()
}
RazorEngine.NetCore
到了.NET Core时代,我看了下FreeSql.Generator用的这个类库RazorEngine.NetCore,实现动态操作cshtml,生成需要的文本。
Razor Engine是基于微软Razor解析的模板引擎,它允许你使用Razor语法构建动态模板,你只需要使用Engine的静态方法,Engine.Razor.RunCompile等。
创建一个控制台应用,然后安装包。
Install-Package RazorEngine.NetCore
using RazorEngine;
using RazorEngine.Templating; // For extension methods.
string template = "Hello @Model.Name, welcome to RazorEngine!";
var result = Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
Console.WriteLine(result);
- 输出如下内容
Hello World, welcome to RazorEngine!
此处使用的RunCompile方法是扩展方法,您需要引用RazorEngine.Templating命名空间。
The "templateKey" 保持唯一值,比如使用guid值。字符串,并且你可以根据此字符串key重新运行缓存的模板。
如果再次根据此key,可使用原本的模板。
var result = Engine.Razor.Run("templateKey", null, new { Name = "Max" });
- 会输出如下内容
Hello Max, welcome to RazorEngine!
上面中的RunCompile第三个参数,传null,因为我们第四个参数使用的是匿名类,
根目录创建一个HelloWord.cshtml,要选择属性,->如果较新则复制 内容,
Hello @Model.Name, welcome to RazorEngine!
控制台如下代码。
string templateFilePath = "HelloWorld.cshtml";
var templateFile = File.ReadAllText(templateFilePath);
string templateFileResult = Engine.Razor.RunCompile(templateFile, Guid.NewGuid().ToString(), null, new
{
Name = "World"
});
Console.WriteLine(templateFileResult);
- 控制台输出
Hello World, welcome to RazorEngine!
- 使用强类型 CopyRightUserInfo.cs生成一个版权所有
using System;
namespace OvOv.Razor
{
public class CopyRightUserInfo
{
public string UserName { get; set; }
public string EmailAddress { get; set; }
public DateTime CreateTime { get; set; }
public string FileRemark { get; set; }
}
}
根目录创建一个CopyRightTemplate.cshtml,要选择属性,->如果较新则复制 内容,
@{
var gen = Model as OvOv.Razor.CopyRightUserInfo;
}
//=============================================================
// 创建人: @gen.UserName
// 创建时间: @gen.CreateTime
// 邮箱: @gen.EmailAddress
//==============================================================
控制台如下代码。
string copyRightTemplatePath = "CopyRightTemplate.cshtml";
var copyRightTemplate = File.ReadAllText(copyRightTemplatePath);
string copyRightResult = Engine.Razor.RunCompile(copyRightTemplate, Guid.NewGuid().ToString(), typeof(CopyRightUserInfo), new CopyRightUserInfo
{
CreateTime = DateTime.Now,
EmailAddress = "710277267@qq.com",
UserName = "IGeekFan"
});
Console.WriteLine(copyRightResult);
Console.ReadKey();
- 控制台输出
//=============================================================
// 创建人: IGeekFan
// 创建时间: 2020/6/23 18:14:08
// 邮箱: 710277267@qq.com
//==============================================================
全放到控制台下,输出如下结果。代码生成器最重要的一点解决了,我们就能实现自己的代码生成器,先构建自己的模板,实现输入(命令行,WPF,WEB端及更多),输出(生成文件)。
- 以上源码已放到示例代码中 https://github.com/luoyunchong/dotnetcore-examples/blob/master/aspnetcore-freesql/OvOv.Razor/Program.cs
源码解析
首先这是一个控制台应用,Main(string[] args)可接收多个参数。
- 处理无参数,--help
- 处理args数组,解析出所有的参数,如果没有设置,则为默认值。(处理一些参数异常问题)最重要的是根据-Razor,选定对应的模板。
ArgsRazor=""//根据-Razor 1 不是2 还是模板的路径,取出的模板文本值。
var razorId = Guid.NewGuid().ToString("N");
RazorEngine.Engine.Razor.Compile(ArgsRazor, razorId);
- 根据数据库连接串,取出参数过滤后的表,视图,存储过程
- 循环数据库的表等,
- model为模板中需要的数据
- razorId与上文的razorId相同,
- sw为生成后的文本保存的值。
var sw = new StringWriter();
var model = new RazorModel(fsql, ArgsNameSpace, ArgsNameOptions, tables, table);
RazorEngine.Engine.Razor.Run(razorId, sw, null, model);
- 将sw字符串保存生成类.cs文件(根据参数配置生成文件名)
- 另外生成一个__重新生成.bat,__razor.cshtml.txt,方便后续用户重新生成实体类。
FreeSql.Tools
这是 FreeSql 衍生出来的辅助工具包,内含生成器等功能;作者:mypeng1985
因为这个不兼容mac,linux,所以作者建议使用dotnet-tool 命令行工具生成实体类,从而支持MAC/Linux系统。对于不是使用FreeSql的开发者,也能使用此工具,你只需要修改对应的模板即可。
使用方式:不多介绍。
- https://github.com/2881099/Freesql.tools
- 分为WPF ,WinForm + DSkin 版本(套网页)
- 看了下代码,底层生成代码逻辑也是用的RazorEngine .NET Framework 下的RazorEngine代码生成介绍
预览图
FreeSql.Generator命令行代码生成器是如何实现的的更多相关文章
- 转:windows下命令行工具
转自: http://www.cnblogs.com/haochuang/p/5593411.html Windows下CMD不好用,远没有Linux,或者一些SSH工具用起来方便.其实Windows ...
- 10款Windows命令行工具
Windows下CMD不好用,远没有Linux,或者一些SSH工具用起来方便.其实Windows下,也有一些不错的工具替代CMD: 0.powercmd经过比较,我最终选择了这款,这里补充一下截图:
- Mybatis上路_05-使用命令行自动生成
http://my.oschina.net/vigiles/blog/125127 目录[-] 1.数据准备: 1)建库: 2)建表: 3)预设数据: 2.编写Generator执行配置文件: 3.搭 ...
- Mybatis上路_05-使用命令行自动生成【转】
http://my.oschina.net/vigiles/blog/125127 Mybatis上路_05-使用命令行自动生成 1人收藏此文章, 我要收藏 发表于1个月前(2013-04-24 ...
- 十分钟用 Node 命令行工具打造 react-cli 脚手架
如果你有以下想法: 每次新开项目需要copy一堆文件/文件夹,太烦!想要快速建立工程 用了vue-cli.react-app,羡慕!想要自己做一个 你只需花十分钟时间,做一个Node命令行工具,打造属 ...
- 使用Maven命令行快速创建项目骨架(archetype)
> mvn archetype:generate 接下来就会输出一些列带索引变化的archetype项可供我们选择,然后提示我们选择一个编号,可以直接回车选择默认的编号(392),然后就跟着 ...
- QT uic rcc moc 命令行使用
QT uic rcc moc 命令行使用 PS C:\Users\lsgx> uic.exe --help Usage: C:\Qt\Qt5.5.1\5.5\msvc2012\bin\uic.e ...
- Ionic2的CLI的命令行
http://blog.csdn.net/qq_33315185/article/details/68067747 在我们开发Ionic app的时候 CLI 是一个非常重要的工具.CLI包含了很多开 ...
- 【amad】cookiecutter -- 一个命令行工具,使用项目模版来构建项目
动机 简介 个人评分 动机 一般的框架都有脚手架工具,但是并不会让所有人满意. 简介 cookiecutter1是一个Python实现的命令行工具,可以通过项目模版来构建项目. 它的特性包括: 跨平台 ...
随机推荐
- springboot 启动报错"No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' available"
1.问题 springboot启动报错 "D:\Program Files\Java\jdk-11\bin\java.exe" -XX:TieredStopAtLevel=1 -n ...
- Java找零钱算法
买东西过程中,卖家经常需要找零钱.现用代码实现找零钱的方法,要求优先使用面额大的纸币,假设卖家有足够数量的各种面额的纸币. 下面给出的算法比较简单,也符合人的直觉:把找零不断地减掉小于它的最大面额的纸 ...
- SpringBoot系列—简单的邮件系统
1. 效果发送效果图 2. 邮件开发准备工作 3. springboot引入mail服务 4. 启动应用,开始4种邮件发送测试 1. 效果发送效果图 连续发送了四封邮件:普通文本邮件,带附件的邮件,内 ...
- cors跨越深度刨析
解决跨域的方式JSOP,和CORS JSONP不做介绍了. CORS跨域: 参考阮一峰http://www.ruanyifeng.com/blog/2016/04/cors.html 官方:https ...
- 泛微 e-cology OA 前台SQL注入漏洞
0x00概述 该漏洞是由于OA系统的WorkflowCenterTreeData接口在收到用户输入的时候未进行安全过滤,oracle数据库传入恶意SQL语句,导致SQL漏洞. 0x01影响范围 使用o ...
- django-CBV刨析、模板层
今日内容概要 CBV源码剖析 模版层 模版语法传值 模版语法之过滤器 模版语法之标签 自定义过滤器.标签及inclusion_tag 模版的继承 模版的导入 FBV与CBV ""& ...
- 网站的安全性对seo优化至关重要-智狐SEO顾问
网站的安全性对seo优化至关重要 作者:智狐zhihuseo 从大的范围来看,网站安全性能也属于seo的范畴之一.域名被恶意泛解析就是网站安全性能低下的特征之一,如果网站域名被恶意泛解析,会直接 ...
- vue 使用 elementUI 和 antd 的细微差别
Checkbox a-checkbox 没有value属性,绑定用checked Collapse 使用折叠面板的时候,antd 的层级关系是 .ant-collapse >.ant-colla ...
- [译]深入理解JVM Understanding JVM Internals
转载: 英文原版地址:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/ 翻不了墙的可以看这个英文版:https: ...
- Spring Boot笔记(一) springboot 集成 swagger-ui
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.添加依赖 <!--SpringBoot整合Swagger-ui--> <depen ...