.NET Core实战项目之CMS 第十一章 开发篇-数据库生成及实体代码生成器开发
上篇給大家從零開始搭建了一個(gè)我們的ASP.NET Core CMS系統(tǒng)的開發(fā)框架,具體為什么那樣設(shè)計(jì)我也已經(jīng)在第十篇文章中進(jìn)行了說明。不過文章發(fā)布后很多人都說了這樣的分層不是很合理,什么數(shù)據(jù)庫實(shí)體應(yīng)該跟倉儲(chǔ)放在一起形成領(lǐng)域?qū)ο?#xff0c;什么ViewModel應(yīng)該放在應(yīng)用層結(jié)構(gòu)倉儲(chǔ)層與UI層。其實(shí)我想說的是,這樣都沒問題,看你自己的理解了!我上篇文章已經(jīng)說了,如果你愿意,完全可以把所有的層融合在一起,隨意合并分離這個(gè)依你個(gè)人喜好。我也是本著簡(jiǎn)單原則以及合適原則的思想來進(jìn)行那樣的分層結(jié)構(gòu),覺得這樣層次更分明些。還有雖然現(xiàn)在DDD的思想很流行,但是實(shí)現(xiàn)起來確很復(fù)雜,小項(xiàng)目就別那樣折騰了。如果你有不同的意見,歡迎加群討論。什么?你問我群號(hào)?自己找去,我才不會(huì)告訴你!
本文已收錄至《.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第一章 入門篇-開篇及總體規(guī)劃》作者:依樂祝原文地址:https://www.cnblogs.com/yilezhu/p/10112406.html
寫在前面
今天我們就進(jìn)入.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS的開發(fā)篇了,在開始之前呢我們首先需要把我們前面設(shè)計(jì)的邏輯模型轉(zhuǎn)換成對(duì)應(yīng)的物理模型,再根據(jù)我們物理模型生成相應(yīng)的數(shù)據(jù)庫腳本,接著我們就新建數(shù)據(jù)庫,然后執(zhí)行下我們生成的腳本即可。當(dāng)然這么多表如果一個(gè)一個(gè)的寫對(duì)應(yīng)的數(shù)據(jù)庫實(shí)體模型,一個(gè)一個(gè)的寫倉儲(chǔ)層代碼以及服務(wù)層代碼,感覺就是在搬磚啊,有木有,所以當(dāng)然得自己實(shí)現(xiàn)個(gè)代碼生成器來自動(dòng)生成這些代碼了!下面我們一步步來先生成下數(shù)據(jù)庫然后再打造一個(gè)實(shí)體模型的代碼生成器吧!
數(shù)據(jù)庫生成
生成物理模型
首先用pdm打開我們?cè)O(shè)計(jì)的邏輯模型文件,后綴名是ldm的文件,如下圖所示:
依次點(diǎn)擊“Tools”-》"Generate Logical Data Model",如下圖所示。或者直接使用快捷鍵Ctrl+Shift+P 打開物理模型生成選項(xiàng)對(duì)話框。
如下圖所示選擇號(hào)對(duì)應(yīng)的數(shù)據(jù)庫后,自定義物理模型的名稱代碼后點(diǎn)擊確定即可生成物理模型。這里數(shù)據(jù)庫類型有很多選擇如:mysql,sqlserver,oracle等等,我們選擇sqlserver2008,你可以隨意從下拉框選擇一個(gè)數(shù)據(jù)庫進(jìn)行生成(當(dāng)然要跟你的數(shù)據(jù)庫對(duì)應(yīng))!
注意這里生成的物理模型默認(rèn)是不會(huì)生成注釋的如下圖所示:
怎么辦呢?如何才能講Name 列的內(nèi)容拷貝到Comment這個(gè)里面呢?因?yàn)檫@個(gè)Commment里面的內(nèi)容才會(huì)真正的轉(zhuǎn)換到數(shù)據(jù)庫字段的注釋。
這時(shí)候你需要Tools->Execute Commands->Edit/Run Scripts (或者快捷鍵Ctrl+Shift+X)打開腳本執(zhí)行的窗口,然后把下面的代碼拷貝進(jìn)行 run一下即可。
'代碼一:將Name中的字符COPY至Comment中Option ? Explicit
ValidationMode ? = ? True
InteractiveMode ? = ? im_Batch
Dim ? mdl ? ' ? the ? current ? model
' ? get ? the ? current ? active ? model
Set ? mdl ? = ? ActiveModel
If ? (mdl ? Is ? Nothing) ? Then
? ? ?MsgBox ? "There ? is ? no ? current ? Model "
ElseIf ? Not ? mdl.IsKindOf(PdPDM.cls_Model) ? Then
? ? ?MsgBox ? "The ? current ? model ? is ? not ? an ? Physical ? Data ? model. "
Else
? ? ?ProcessFolder ? mdl
End ? If
' ? This ? routine ? copy ? name ? into ? comment ? for ? each ? table, ? each ? column ? and ? each ? view
' ? of ? the ? current ? folder
Private ? sub ? ProcessFolder(folder)
? ? ?Dim ? Tab ? 'running ? ? table
? ? ?for ? each ? Tab ? in ? folder.tables
? ? ? ? ? ?if ? not ? tab.isShortcut ? then
? ? ? ? ? ? ? ? ?tab.comment ? = ? tab.name
? ? ? ? ? ? ? ? ?Dim ? col ? ' ? running ? column
? ? ? ? ? ? ? ? ?for ? each ? col ? in ? tab.columns
? ? ? ? ? ? ? ? ? ? ? ?col.comment= ? col.name
? ? ? ? ? ? ? ? ?next
? ? ? ? ? ?end ? if
? ? ?next
? ? ?Dim ? view ? 'running ? view
? ? ?for ? each ? view ? in ? folder.Views
? ? ? ? ? ?if ? not ? view.isShortcut ? then
? ? ? ? ? ? ? ? ?view.comment ? = ? view.name
? ? ? ? ? ?end ? if
? ? ?next
? ? ?' ? go ? into ? the ? sub-packages
? ? ?Dim ? f ? ' ? running ? folder
? ? ?For ? Each ? f ? In ? folder.Packages
? ? ? ? ? ?if ? not ? f.IsShortcut ? then
? ? ? ? ? ? ? ? ?ProcessFolder ? f
? ? ? ? ? ?end ? if
? ? ?Next
end ? sub
這里腳本執(zhí)行的很快,你也可以把腳本保存起來下次再用,執(zhí)行后的效果如下所示:
我們的Comment這一行的內(nèi)容已經(jīng)跟Name一樣了!
數(shù)據(jù)庫腳本生成
首先打開我們生成的物理模型,擴(kuò)展名為pdm的文件,如下圖所示,乍一看跟物理模型差不多,實(shí)際上還是有區(qū)別的!
然后依次如下圖所示選擇“Database”->"Generate Database" 或者快捷鍵Ctrl+G打開數(shù)據(jù)庫生成選項(xiàng)對(duì)話框
如下圖所示設(shè)置一下生成的數(shù)據(jù)庫腳本的路徑以及腳本名稱即可生成數(shù)據(jù)庫腳本文件,如下圖所示:
到我們上面設(shè)置的文件夾里即可查看到我們生成的數(shù)據(jù)庫腳本,如下圖所示:
數(shù)據(jù)庫生成
打開我們的數(shù)據(jù)庫,并新建一個(gè)名為CzarCms的新的數(shù)據(jù)庫,如下圖所示:
選擇我們新建的數(shù)據(jù)庫,然后按照如下圖所示的方式打開我們剛才生成的數(shù)據(jù)庫腳本
如下圖所示確認(rèn)一下目前選擇的是你剛新建的數(shù)據(jù)庫,然后點(diǎn)擊執(zhí)行,執(zhí)行下腳本
不出以外的話會(huì)出現(xiàn)如下圖所示的“命令已成功完成”的消息,這表示腳本執(zhí)行成功了,然后刷新下我們剛才的數(shù)據(jù)庫,可以看到我們的表已經(jīng)生成成功了!
這里你可以檢查下,看看生成的數(shù)據(jù)庫表有沒有問題,如果有問題的話,重新走一遍流程生成腳本然后執(zhí)行下就行了,不過需要注意的是,如果你數(shù)據(jù)庫中有數(shù)據(jù)就要當(dāng)心了,重新生成的腳本會(huì)drop掉你的表重新創(chuàng)建,所以如果是個(gè)別字段出問題的話就邏輯模型以及物理模型修改后,手動(dòng)在數(shù)據(jù)庫中修改即可!
這里我給每個(gè)表的主鍵設(shè)計(jì)了自增,給isdelete等等設(shè)置了默認(rèn)的0,以及addtime設(shè)置了getdate()等等。
實(shí)體模型生成器編寫
好了,上面我已經(jīng)帶著你一步一步的演示了數(shù)據(jù)庫的創(chuàng)建過程,下面我就帶著你實(shí)現(xiàn)一個(gè)簡(jiǎn)單的POCO實(shí)體對(duì)象的代碼生成器吧!什么?市面上不是有很多代碼生成器嗎?靠,我就是要帶著你自己實(shí)現(xiàn)一個(gè),咋滴?是用別人的爽,還是用自己實(shí)現(xiàn)的爽呢?自己琢磨吧!
思考
大家先腦補(bǔ)一下,如果是你想根據(jù)數(shù)據(jù)庫實(shí)現(xiàn)一個(gè)代碼生成器你的思路是怎樣的呢?是不是首先得獲取下數(shù)據(jù)庫里面的所有的表,然后獲取這些表對(duì)應(yīng)的列以及列的類型,是否為空等等信息。然后再建一個(gè)模板,循環(huán)這些表的信息來根據(jù)模板創(chuàng)建對(duì)應(yīng)的文件呢。至于模板文件可能你會(huì)想到T4或者CodeSmish模板等等,可這些都太復(fù)雜了,復(fù)雜的語法以及靈活性的問題我這里選擇另一個(gè)文本文件的形式來進(jìn)行代碼的生成。
這個(gè)代碼生成器的靈感以及部分代碼來自于Zxw.Framework.NetCore,這個(gè)框架的github地址是:https://github.com/VictorTzeng/Zxw.Framework.NetCore/tree/master/Zxw.Framework.NetCore 有興趣的小伙伴可以看下。
下面就讓我們簡(jiǎn)單實(shí)現(xiàn)下我們自己的實(shí)體模型代碼生成器吧.
實(shí)體代碼生成器
首先我們創(chuàng)建一個(gè)Option對(duì)象來接收我們所需要的參數(shù),比如說:數(shù)據(jù)庫類型,數(shù)據(jù)庫連接字符串,作者,實(shí)體模型的命名空間等等,如下所示:
/// <summary>? ?/// yilezhu
? ?/// 2018.12.12
? ?/// 代碼生成選項(xiàng)
? ?/// </summary>
? ?public class CodeGenerateOption
? ?{
? ? ? ?/// <summary>
? ? ? ?/// 數(shù)據(jù)庫連接字符串
? ? ? ?/// </summary>
? ? ? ?public string ConnectionString { get; set; }
? ? ? ?/// <summary>
? ? ? ?/// 數(shù)據(jù)庫類型
? ? ? ?/// </summary>
? ? ? ?public string DbType ?{ get; set; }
? ? ? ?/// <summary>
? ? ? ?/// 作者
? ? ? ?/// </summary>
? ? ? ?public string Author { get; set; }
? ? ? ?/// <summary>
? ? ? ?/// 代碼生成時(shí)間
? ? ? ?/// </summary>
? ? ? ?public string GeneratorTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
? ? ? ?/// <summary>
? ? ? ?/// 輸出路徑
? ? ? ?/// </summary>
? ? ? ?public string OutputPath { get; set; }
? ? ? ?/// <summary>
? ? ? ?/// 實(shí)體命名空間
? ? ? ?/// </summary>
? ? ? ?public string ModelsNamespace { get; set; }
? ?}
從數(shù)據(jù)庫里面獲取所有表的腳本,這里我只是簡(jiǎn)單的實(shí)現(xiàn)了下SqlServer的代碼,后續(xù)我會(huì)對(duì)這塊進(jìn)行提取封裝,并支持MySql,Oracle,PSQL等等:
//TODO 從數(shù)據(jù)庫獲取表列表以及生成實(shí)體對(duì)象? ? ? ? ? ?if (_options.DbType != DatabaseType.SqlServer.ToString())
? ? ? ? ? ? ? ?throw new ArgumentNullException("這是我的錯(cuò),目前只支持MSSQL數(shù)據(jù)庫的代碼生成!后續(xù)更新MySQL");
? ? ? ? ? ?DatabaseType dbType = DatabaseType.SqlServer;
? ? ? ? ? ?string strGetAllTables = @"SELECT DISTINCT d.name as TableName, f.value as TableComment
FROM ? ? ?sys.syscolumns AS a LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.systypes AS b ON a.xusertype = b.xusertype INNER JOIN
? ? ? ? ? ? ? ?sys.sysobjects AS d ON a.id = d.id AND d.xtype = 'U' AND d.name <> 'dtproperties' LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.syscomments AS e ON a.cdefault = e.id LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.extended_properties AS g ON a.id = g.major_id AND a.colid = g.minor_id LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.extended_properties AS f ON d.id = f.major_id AND f.minor_id = 0";
? ? ? ? ? ?List<DbTable> tables = null;
? ? ? ? ? ?using (var conn = new SqlConnection(_options.ConnectionString))
? ? ? ? ? ?{
? ? ? ? ? ? ? ?tables = conn.Query<DbTable>(strGetAllTables).ToList();
遍歷每個(gè)表然后獲取每個(gè)表對(duì)應(yīng)的列(也是只實(shí)現(xiàn)的SqlServer的代碼)
tables.ForEach(item =>? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?string strGetTableColumns = @"SELECT ? a.name AS ColName, CONVERT(bit, (CASE WHEN COLUMNPROPERTY(a.id, a.name, 'IsIdentity')
? ? ? ? ? ? ? ?= 1 THEN 1 ELSE 0 END)) AS IsIdentity, CONVERT(bit, (CASE WHEN
? ? ? ? ? ? ? ? ? ?(SELECT ? COUNT(*)
? ? ? ? ? ? ? ? ? ? FROM ? ? ?sysobjects
? ? ? ? ? ? ? ? ? ? WHERE ? (name IN
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (SELECT ? name
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FROM ? ? ?sysindexes
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?WHERE ? (id = a.id) AND (indid IN
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(SELECT ? indid
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FROM ? ? ?sysindexkeys
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? WHERE ? (id = a.id) AND (colid IN
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (SELECT ? colid
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FROM ? ? ?syscolumns
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?WHERE ? (id = a.id) AND (name = a.name))))))) AND (xtype = 'PK'))
? ? ? ? ? ? ? ?> 0 THEN 1 ELSE 0 END)) AS IsPrimaryKey, b.name AS ColumnType, COLUMNPROPERTY(a.id, a.name, 'PRECISION')
? ? ? ? ? ? ? ?AS ColumnLength, CONVERT(bit, (CASE WHEN a.isnullable = 1 THEN 1 ELSE 0 END)) AS IsNullable, ISNULL(e.text, '')
? ? ? ? ? ? ? ?AS DefaultValue, ISNULL(g.value, ' ') AS Comment
FROM ? ? ?sys.syscolumns AS a LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.systypes AS b ON a.xtype = b.xusertype INNER JOIN
? ? ? ? ? ? ? ?sys.sysobjects AS d ON a.id = d.id AND d.xtype = 'U' AND d.name <> 'dtproperties' LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.syscomments AS e ON a.cdefault = e.id LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.extended_properties AS g ON a.id = g.major_id AND a.colid = g.minor_id LEFT OUTER JOIN
? ? ? ? ? ? ? ?sys.extended_properties AS f ON d.id = f.class AND f.minor_id = 0
WHERE ? (b.name IS NOT NULL) AND (d.name = @TableName)
ORDER BY a.id, a.colorder";
? ? ? ? ? ? ? ? ? ?item.Columns = conn.Query<DbTableColumn>(strGetTableColumns, new
? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?TableName = item.TableName
? ? ? ? ? ? ? ? ? ?}).ToList();
接下來就是對(duì)數(shù)據(jù)庫獲取的列進(jìn)行一個(gè)轉(zhuǎn)換,根據(jù)數(shù)據(jù)庫字段類型轉(zhuǎn)換成對(duì)應(yīng)的C#類型了
item.Columns.ForEach(x =>? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?var csharpType = DbColumnTypeCollection.DbColumnDataTypes.FirstOrDefault(t =>
? ? ? ? ? ? ? ? ? ? ? ? ? ?t.DatabaseType == dbType && t.ColumnTypes.Split(',').Any(p =>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?p.Trim().Equals(x.ColumnType, StringComparison.OrdinalIgnoreCase)))?.CSharpType;
? ? ? ? ? ? ? ? ? ? ? ?if (string.IsNullOrEmpty(csharpType))
? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ?throw new SqlTypeException($"未從字典中找到\"{x.ColumnType}\"對(duì)應(yīng)的C#數(shù)據(jù)類型,請(qǐng)更新DbColumnTypeCollection類型映射字典。");
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ?x.CSharpType = csharpType;
? ? ? ? ? ? ? ? ? ?});
既然所有的表以及表對(duì)應(yīng)的列我們都拿到了,那么我們就可以進(jìn)行代碼的生成了,當(dāng)然在生成之前還得創(chuàng)建我們的模板文件:
// 本代碼由代碼生成器生成請(qǐng)勿隨意改動(dòng)// 生成時(shí)間 ?{GeneratorTime}
using System;
namespace {ModelsNamespace}
{
? ?/// <summary>
? ?/// {Author}
? ?/// {GeneratorTime}
? ?/// {Comment}
? ?/// </summary>
? ?public class {ModelName}
? ?{
? ? ? ?{ModelProperties}
? ?}
}
看到?jīng)]有,很簡(jiǎn)單的POCO對(duì)象的樣子,接下來就是生成對(duì)應(yīng)的模板了,具體怎么生成呢?思考下:是不是首先讀取模板文件到一個(gè)string里面,然后就是簡(jiǎn)單的replace了!很簡(jiǎn)單吧,具體的代碼我都上傳到了Github上,文章末尾我會(huì)給出地址。另外為了大家引用的方便我已經(jīng)把這個(gè)Czar.Cms.Core項(xiàng)目制作成了Nuget包,大家只需要搜索這個(gè)包引用下就可以用了!什么?Nuget包怎么引用啊?騷年你可以上天了~
測(cè)試實(shí)體代碼生成器
Czar.Cms.Test 這個(gè)項(xiàng)目添加Nuget包引用,引用后的Nuget如下所示:
接下來就是新建一個(gè)測(cè)試類,然后創(chuàng)建一個(gè)依賴注入容器,并把我們需要的Option傳遞進(jìn)去,如下所示:
/// <summary>? ? ? ?/// 構(gòu)造依賴注入容器,然后傳入?yún)?shù)
? ? ? ?/// </summary>
? ? ? ?/// <returns></returns>
? ? ? ?public IServiceProvider BuildServiceForSqlServer()
? ? ? ?{
? ? ? ? ? ?var services = new ServiceCollection();
? ? ? ? ? ?services.Configure<CodeGenerateOption>(options =>
? ? ? ? ? ?{
? ? ? ? ? ? ? ?options.ConnectionString = "Data Source=.;Initial Catalog=CzarCms;User ID=sa;Password=1;Persist Security Info=True;Max Pool Size=50;Min Pool Size=0;Connection Lifetime=300;";//這個(gè)必須
? ? ? ? ? ? ? ?options.DbType = DatabaseType.SqlServer.ToString();//數(shù)據(jù)庫類型是SqlServer,其他數(shù)據(jù)類型參照枚舉DatabaseType//這個(gè)也必須
? ? ? ? ? ? ? ?options.Author = "yilezhu";//作者名稱,隨你,不寫為空
? ? ? ? ? ? ? ?options.OutputPath = @"E:\workspace\vs2017\Czar.Cms\src\Czar.Cms.Models";//實(shí)體模型輸出路徑,為空則默認(rèn)為當(dāng)前程序運(yùn)行的路徑
? ? ? ? ? ? ? ?options.ModelsNamespace = "Czar.Cms.Models";//實(shí)體命名空間
? ? ? ? ? ?});
? ? ? ? ? ?services.AddSingleton<CodeGenerator>();//注入Model代碼生成器
? ? ? ? ? ?return services.BuildServiceProvider(); //構(gòu)建服務(wù)提供程序
? ? ? ?}
接著就是寫我們的測(cè)試方法了,代碼如下:
[Fact]? ? ? ?public void GeneratorModelForSqlServer()
? ? ? ?{
? ? ? ? ? ?var serviceProvider= BuildServiceForSqlServer();
? ? ? ? ? ?var codeGenerator = serviceProvider.GetRequiredService<CodeGenerator>();
? ? ? ? ? ?codeGenerator.GenerateModelCodesFromDatabase();
? ? ? ? ? ?Assert.Equal(0,0);
? ? ? ?}
運(yùn)行一下我們的Live Unit Testing 然后看一下我們的Czar.Cms.Models下面已經(jīng)生成了對(duì)應(yīng)的實(shí)體文件,如下圖所示:
隨便打開一個(gè)看小效果如下:我標(biāo)注的你猜猜看都是對(duì)應(yīng)的哪個(gè)Options
開源地址
這個(gè)系列教程的源碼我會(huì)開放在GitHub以及碼云上,有興趣的朋友可以下載查看!覺得不錯(cuò)的歡迎StarGitHub:https://github.com/yilezhu/Czar.Cms碼云:https://gitee.com/yilezhu/Czar.Cms如果你覺得這個(gè)系列對(duì)您有所幫助的話,歡迎以各種方式進(jìn)行贊助,當(dāng)然給個(gè)Star支持下也是可以滴!另外一種最簡(jiǎn)單粗暴的方式就是下面這種直接關(guān)注我們的公眾號(hào)了:第一時(shí)間收到更新推送。
總結(jié)
這篇文章我們一步一步的生成了我們的數(shù)據(jù)庫,然后手把手帶著你實(shí)現(xiàn)了我們自己的實(shí)體模型代碼生成器來簡(jiǎn)化我們的開發(fā)過程。接下來我們就開始實(shí)現(xiàn)倉儲(chǔ)層應(yīng)用層的代碼了,同時(shí)我們會(huì)提取通用部分的代碼來進(jìn)行模板代碼生成來簡(jiǎn)化我們的工作!俗話說的好,不會(huì)偷懶的程序員不是一個(gè)好爸爸,好丈夫,好兒子,減少代碼的時(shí)間多抽點(diǎn)時(shí)間陪陪家人吧!如果你有其他想法可以在下方留言,或者加群跟大伙一起討論。共同進(jìn)步!共勉!
原文
相關(guān)文章:
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第一章 入門篇-開篇及總體規(guī)劃
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第二章 入門篇-快速入門ASP.NET Core看這篇就夠了
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第三章 入門篇-源碼解析配置文件及依賴注入
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第四章 入門篇-Git的快速入門及實(shí)戰(zhàn)演練
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第五章 入門篇-Dapper的快速入門看這篇就夠了
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第六章 入門篇-Vue的快速入門及其使用
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第七章 設(shè)計(jì)篇-用戶權(quán)限極簡(jiǎn)設(shè)計(jì)全過程
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第八章 設(shè)計(jì)篇-內(nèi)容管理極簡(jiǎn)設(shè)計(jì)全過程
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第九章 設(shè)計(jì)篇-白話架構(gòu)設(shè)計(jì)
.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS 第十章 設(shè)計(jì)篇-系統(tǒng)開發(fā)框架設(shè)計(jì)
原文地址:https://www.cnblogs.com/yilezhu/p/10112406.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的.NET Core实战项目之CMS 第十一章 开发篇-数据库生成及实体代码生成器开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软推出 VS Code 新特性,为 T
- 下一篇: ASP.NET Core WebAPI中