FreeSql.Generator命令行代码生成器是如何实现的
目錄
FreeSql介紹
FreeSql.Generator
RazorEngine.NetCore
源碼解析
FreeSql.Tools
FreeSql
FreeSql 是功能強(qiáng)大的對(duì)象關(guān)系映射技術(shù)(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.0+ 或 Xamarin。
有一個(gè)強(qiáng)大的ORM,也方便我們開(kāi)發(fā)一個(gè)代碼生成器。
一般情況下,我們開(kāi)發(fā)數(shù)據(jù)庫(kù)相關(guān)的應(yīng)用,主要分為三種code first、db first、model first
我只用過(guò)前二種,
code first,代碼優(yōu)先,數(shù)據(jù)庫(kù)都是根據(jù)實(shí)體類(lèi)生成,所有的關(guān)系,可以是邏輯關(guān)聯(lián),也可以是物理關(guān)聯(lián)。
DB First: 數(shù)據(jù)庫(kù)優(yōu)先,直接設(shè)計(jì)表結(jié)構(gòu),用設(shè)計(jì)工具生成表,設(shè)計(jì)主鍵,外鍵、索引,關(guān)聯(lián)關(guān)系等。
當(dāng)我們使用DB First時(shí),設(shè)計(jì)好的數(shù)據(jù)庫(kù),我們?cè)趺瓷蛇@些實(shí)體類(lèi)、通用的代碼、控制器、服務(wù)層、Dto呢。今天我來(lái)給大家介紹一下FreeSql項(xiàng)目中的一些工具。當(dāng)然,不使用此ORM的小伙伴也能使用此工具,因?yàn)樗峭ㄓ谩?/p>
FreeSql.Generator 命令行方式
通過(guò)幾行命令,就可實(shí)現(xiàn)生成項(xiàng)目中通用的代碼結(jié)構(gòu),不需要復(fù)制一段代碼后修改,加快開(kāi)發(fā)速度,減少重復(fù)勞動(dòng),少用一根頭發(fā)。
由于每個(gè)人的項(xiàng)目結(jié)構(gòu),代碼位置各不相同,對(duì)于ORM來(lái)說(shuō),不同的業(yè)務(wù)邏輯各不相同,所以該項(xiàng)目沒(méi)有相應(yīng)的模板,相信使用過(guò)Razor的同學(xué)一定能實(shí)現(xiàn)自己的模板。
1-2年前,我和一個(gè)學(xué)長(zhǎng)也寫(xiě)過(guò)代碼生成器,這里分享一下當(dāng)時(shí)做項(xiàng)目時(shí)的一些模板,https://github.com/i542873057/SJNScaffolding/tree/master/SJNScaffolding.RazorPage/Templates,該項(xiàng)目是基于 . NET Core+Razor Page,由于已離職,所以沒(méi)有繼續(xù)維護(hù),這些模板都和ABP相關(guān),當(dāng)時(shí)提取了一些通用的功能,單表操作,可以直接生成前后端功能,只需要在word中按統(tǒng)一的格式寫(xiě)好數(shù)據(jù)字典的文檔,直接復(fù)制到系統(tǒng),即可根據(jù)空格,定義類(lèi)型等方式解析字段。
回到FreeSql.Generator 命令行
對(duì)于此工具的使用可參考?https://github.com/dotnetcore/FreeSql/wiki/DbFirst
源碼位置?https://github.com/dotnetcore/FreeSql/tree/master/Extensions/FreeSql.Generator
前提是本地安裝了.net?core 3.1 的sdk.
怎么使用呢。
安裝 dotnet-tool 生成實(shí)體類(lèi)
新建目錄,在地址欄輸入 cmd 快速打開(kāi)命令窗口,輸入命令:
我們可以看到
C:\Users\igeekfan\Desktop\code>FreeSql.Generator --help____ ____ __/ __/ ____ ___ ___ / __/ ___ _ / // _/ / __// -_)/ -_) _\ \ / _ `/ / //_/ /_/ \__/ \__/ /___/ \_, / /_//_/# Github # https://github.com/2881099/FreeSql v1.5.0使用 FreeSql 快速生成數(shù)據(jù)庫(kù)的實(shí)體類(lèi)更新工具:dotnet tool update -g FreeSql.Generator# 快速開(kāi)始 #> FreeSql.Generator -Razor 1 -NameOptions 0,0,0,0 -NameSpace MyProject -DB "MySql,Data Source=127.0.0.1;..."-Razor 1 * 選擇模板:實(shí)體類(lèi)+特性-Razor 2 * 選擇模板:實(shí)體類(lèi)+特性+導(dǎo)航屬性-Razor "d:\diy.cshtml" * 自定義模板文件-NameOptions * 總共4個(gè)布爾值,分別對(duì)應(yīng):# 首字母大寫(xiě)# 首字母大寫(xiě),其他小寫(xiě)# 全部小寫(xiě)# 下劃線轉(zhuǎn)駝峰-NameSpace * 命名空間-DB "MySql,Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=數(shù)據(jù)庫(kù);Charset=utf8;SslMode=none;Max pool size=2"-DB "SqlServer,Data Source=.;Integrated Security=True;Initial Catalog=數(shù)據(jù)庫(kù);Pooling=true;Max Pool Size=2"-DB "PostgreSQL,Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=數(shù)據(jù)庫(kù);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 是國(guó)產(chǎn)達(dá)夢(mèng)數(shù)據(jù)庫(kù)-Filter Table+View+StoreProcedure默認(rèn)生成:表+視圖+存儲(chǔ)過(guò)程如果不想生成視圖和存儲(chǔ)過(guò)程 -Filter View+StoreProcedure-Match 正則表達(dá)式,只生成匹配的表,如:dbo\.TB_.+-FileName 文件名,默認(rèn):{name}.cs-Output 保存路徑,默認(rèn)為當(dāng)前 shell 所在目錄推薦在實(shí)體類(lèi)目錄創(chuàng)建 gen.bat,雙擊它重新所有實(shí)體類(lèi)更新命令行
這里lin-cms-dotnetcore這個(gè)項(xiàng)目來(lái)測(cè)試。
數(shù)據(jù)庫(kù)表名是下劃線,字段也是下劃線方式。
-Razor 指定 第一個(gè)模板
-NameOptions 0,0,0,1 最后一個(gè)1,代表 下劃線轉(zhuǎn)駝峰,滿足C#命名規(guī)則
-NameSpace 指定了命名空間 LinCms.Core.Entities
-DB 就是數(shù)據(jù)庫(kù)的相關(guān)配置
mysql 本地地址 127.0.0.1 3306端口 用戶名 root 密碼123456 數(shù)據(jù)庫(kù) lin-cms
-Match book 這樣就能只生成book,支持正則表達(dá)式,如 -Math lin_user 就會(huì)生成以lin_user開(kāi)頭的表。如dbo.TB_.+,會(huì)生成以TB開(kāi)頭的表。即只生成匹配的表
執(zhí)行此命令。
這時(shí)候代碼已經(jīng)生成了
其中一個(gè)代碼 生成如下。這些類(lèi)是partial ,熟悉C#的同學(xué),應(yīng)該知道,類(lèi)的定義使用此關(guān)鍵字,我們能在不同的地方為該類(lèi)擴(kuò)展。以防止重新同步數(shù)據(jù)庫(kù)的結(jié)構(gòu)時(shí),丟失改動(dòng)的字段。
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}}最終效果圖如下
此時(shí)會(huì)生成二個(gè)文件 __重新生成.bat,下次重新點(diǎn)擊他就能重新生成實(shí)體類(lèi)了。
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 指定了這個(gè)txt文件 __razor.cshtml.txt
我們可以定義自己的模板,以生成符合自已業(yè)務(wù)的的代碼,從而實(shí)現(xiàn)快速開(kāi)發(fā)。
我們可以看下模板中的文件內(nèi)容,他就是asp.net下的mvc 結(jié)構(gòu)下的razor后端模板渲染,把這個(gè).txt后綴去掉,就很明了了。對(duì)于asp.net mvc的razor,我們可以將控制器下方法的值替換掉cshtml中的值。這個(gè)過(guò)程是有一個(gè)類(lèi)庫(kù)在幫我們實(shí)現(xiàn)的,叫RazorEngine,不過(guò)那個(gè)是.net framework下的實(shí)踐。.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時(shí)代,我看了下FreeSql.Generator用的這個(gè)類(lèi)庫(kù)RazorEngine.NetCore,實(shí)現(xiàn)動(dòng)態(tài)操作cshtml,生成需要的文本。
Razor Engine是基于微軟Razor解析的模板引擎,它允許你使用Razor語(yǔ)法構(gòu)建動(dòng)態(tài)模板,你只需要使用Engine的靜態(tài)方法,Engine.Razor.RunCompile等。
創(chuàng)建一個(gè)控制臺(tái)應(yīng)用,然后安裝包。
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);輸出如下內(nèi)容
此處使用的RunCompile方法是擴(kuò)展方法,您需要引用RazorEngine.Templating命名空間。
The "templateKey" 保持唯一值,比如使用guid值。字符串,并且你可以根據(jù)此字符串key重新運(yùn)行緩存的模板。
如果再次根據(jù)此key,可使用原本的模板。
var result = Engine.Razor.Run("templateKey", null, new { Name = "Max" });會(huì)輸出如下內(nèi)容
上面中的RunCompile第三個(gè)參數(shù),傳null,因?yàn)槲覀兊谒膫€(gè)參數(shù)使用的是匿名類(lèi),
根目錄創(chuàng)建一個(gè)HelloWord.cshtml,要選擇屬性,->如果較新則復(fù)制 內(nèi)容,
Hello @Model.Name, welcome to RazorEngine!控制臺(tái)如下代碼。
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);控制臺(tái)輸出
使用強(qiáng)類(lèi)型 CopyRightUserInfo.cs生成一個(gè)版權(quán)所有
根目錄創(chuàng)建一個(gè)CopyRightTemplate.cshtml,要選擇屬性,->如果較新則復(fù)制 內(nèi)容,
@{var gen = Model as OvOv.Razor.CopyRightUserInfo; } //============================================================= // 創(chuàng)建人: @gen.UserName // 創(chuàng)建時(shí)間: @gen.CreateTime // 郵箱: @gen.EmailAddress //==============================================================控制臺(tái)如下代碼。
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();控制臺(tái)輸出
全放到控制臺(tái)下,輸出如下結(jié)果。代碼生成器最重要的一點(diǎn)解決了,我們就能實(shí)現(xiàn)自己的代碼生成器,先構(gòu)建自己的模板,實(shí)現(xiàn)輸入(命令行,WPF,WEB端及更多),輸出(生成文件)。
以上源碼已放到示例代碼中?https://github.com/luoyunchong/dotnetcore-examples/blob/master/aspnetcore-freesql/OvOv.Razor/Program.cs
源碼解析
首先這是一個(gè)控制臺(tái)應(yīng)用,Main(string[] args)可接收多個(gè)參數(shù)。
處理無(wú)參數(shù),--help
處理args數(shù)組,解析出所有的參數(shù),如果沒(méi)有設(shè)置,則為默認(rèn)值。(處理一些參數(shù)異常問(wèn)題)最重要的是根據(jù)-Razor,選定對(duì)應(yīng)的模板。
根據(jù)數(shù)據(jù)庫(kù)連接串,取出參數(shù)過(guò)濾后的表,視圖,存儲(chǔ)過(guò)程
循環(huán)數(shù)據(jù)庫(kù)的表等,
model為模板中需要的數(shù)據(jù)
razorId與上文的razorId相同,
sw為生成后的文本保存的值。
將sw字符串保存生成類(lèi).cs文件(根據(jù)參數(shù)配置生成文件名)
另外生成一個(gè)__重新生成.bat,__razor.cshtml.txt,方便后續(xù)用戶重新生成實(shí)體類(lèi)。
FreeSql.Tools
這是 FreeSql 衍生出來(lái)的輔助工具包,內(nèi)含生成器等功能;作者:mypeng1985 因?yàn)檫@個(gè)不兼容mac,linux,所以作者建議使用dotnet-tool 命令行工具生成實(shí)體類(lèi),從而支持MAC/Linux系統(tǒng)。對(duì)于不是使用FreeSql的開(kāi)發(fā)者,也能使用此工具,你只需要修改對(duì)應(yīng)的模板即可。
使用方式:不多介紹。
https://github.com/2881099/Freesql.tools
分為WPF ,WinForm + DSkin 版本(套網(wǎng)頁(yè))
看了下代碼,底層生成代碼邏輯也是用的RazorEngine?.NET Framework 下的RazorEngine代碼生成介紹
預(yù)覽圖
總結(jié)
以上是生活随笔為你收集整理的FreeSql.Generator命令行代码生成器是如何实现的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MongoDB via Dotnet C
- 下一篇: angular 接入 IdentityS