NewLife.XCode是一個有10多年歷史的開源數據中間件,由新生命團隊(2002~2019)開發完成並維護至今,以下簡稱XCode。
整個系列教程會大量結合示例代碼和運行日志來進行深入分析,蘊含多年開發經驗於其中。
開源地址:https://github.com/NewLifeX/X (求star, 620+)
數據模型文件
數據模型文件是XCode數據庫開發的中心,曾經流行和支持的DB First和Entity First,經過10多年優勝劣汰,只剩下Model First。
XCode的數據模型文件就是一個Model.xml,(名字可變),同目錄配套Build.tt,用於在vs里調用XCode生成基於xml模型文件的多個實體類文件。
從nuget安裝NewLife.XCode時,可以看到項目下多了一個Model.xml和build.tt/build_netcore.tt
nfx項目安裝NewLife.XCode才有,netcore項目可從nfx項目中拷貝這兩個文件,或者修改項目為netcore+net45混合項目后再安裝引用。
(!!!安裝XCode后,編譯一次項目,確保輸出目錄中存在newlife.core.dll和xcode.dll,因為build.tt內需要引用這兩個文件,也可以拷貝這兩個文件到別處並修改build.tt內部引用)
其中的Model.xml正是供我們進行數據建模的參考,同時也是XCode內部Membership的模型文件。
<?xml version="1.0" encoding="utf-8"?> <Tables Version="9.6.6663.16294" NameSpace="XCode.Membership" ConnName="Membership" Output="" BaseClass="Entity" xmlns="http://www.newlifex.com/ModelSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.newlifex.com https://raw.githubusercontent.com/NewLifeX/X/master/XCode/ModelSchema.xsd" > <Table Name="User" Description="用戶" DbType="SqlServer" RenderGenEntity="true"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名稱。登錄用戶名" /> <Column Name="Password" DataType="String" Description="密碼" /> <Column Name="DisplayName" DataType="String" Description="昵稱" /> <Column Name="Sex" DataType="Int32" Description="性別。未知、男、女" Type="SexKinds" /> <Column Name="Mail" DataType="String" Description="郵件" /> <Column Name="Mobile" DataType="String" Description="手機" /> <Column Name="Code" DataType="String" Description="代碼。身份證、員工編號等" /> <Column Name="Avatar" DataType="String" Length="200" Description="頭像" /> <Column Name="RoleID" DataType="Int32" Description="角色。主要角色" /> <Column Name="RoleIDs" DataType="String" Length="200" Description="角色組。次要角色集合" /> <Column Name="Online" DataType="Boolean" Description="在線" /> <Column Name="Enable" DataType="Boolean" Description="啟用" /> <Column Name="Logins" DataType="Int32" Description="登錄次數" /> <Column Name="LastLogin" DataType="DateTime" Description="最后登錄" /> <Column Name="LastLoginIP" DataType="String" Description="最后登錄IP" /> <Column Name="RegisterTime" DataType="DateTime" Description="注冊時間" /> <Column Name="RegisterIP" DataType="String" Description="注冊IP" /> </Columns> <Indexes> <Index Columns="Name" Unique="True" /> <Index Columns="RoleID" /> </Indexes> </Table> <Table Name="Role" Description="角色" RenderGenEntity="true"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名稱" /> <Column Name="IsSystem" DataType="Boolean" Description="系統。用於業務系統開發使用,不受數據權限約束,禁止修改名稱或刪除" /> <Column Name="Remark" DataType="String" Description="說明" /> <Column Name="Permission" DataType="String" Length="500" Description="權限。對不同資源的權限,逗號分隔,每個資源的權限子項豎線分隔" /> <Column Name="CreateUserID" DataType="Int32" Description="創建用戶" /> <Column Name="CreateIP" DataType="String" Description="創建地址" /> <Column Name="CreateTime" DataType="DateTime" Description="創建時間" /> <Column Name="UpdateUserID" DataType="Int32" Description="更新用戶" /> <Column Name="UpdateIP" DataType="String" Description="更新地址" /> <Column Name="UpdateTime" DataType="DateTime" Description="更新時間" /> </Columns> <Indexes> <Index Columns="Name" Unique="True" /> </Indexes> </Table> <Table Name="Menu" Description="菜單" BaseType="EntityTree" RenderGenEntity="true"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名稱" /> <Column Name="DisplayName" DataType="String" Description="顯示名" /> <Column Name="FullName" DataType="String" Length="200" Description="全名" /> <Column Name="ParentID" DataType="Int32" Description="父編號" /> <Column Name="Url" DataType="String" Length="200" Description="鏈接" /> <Column Name="Sort" DataType="Int32" Description="排序" /> <Column Name="Icon" DataType="String" Description="圖標" /> <Column Name="Visible" DataType="Boolean" Description="可見" /> <Column Name="Necessary" DataType="Boolean" Description="必要。必要的菜單,必須至少有角色擁有這些權限,如果沒有則自動授權給系統角色" /> <Column Name="Permission" DataType="String" Length="200" Description="權限子項。逗號分隔,每個權限子項名值豎線分隔" /> <Column Name="Remark" DataType="String" Length="200" Description="備注" /> </Columns> <Indexes> <Index Columns="Name" /> <Index Columns="ParentID,Name" Unique="True" /> </Indexes> </Table> <Table Name="Log" Description="日志" ConnName="Log" RenderGenEntity="true"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="Category" DataType="String" Description="類別" /> <Column Name="Action" DataType="String" Description="操作" /> <Column Name="LinkID" DataType="Int32" Description="鏈接" /> <Column Name="UserName" DataType="String" Description="用戶名" /> <Column Name="CreateUserID" DataType="Int32" Description="用戶編號" /> <Column Name="CreateIP" DataType="String" Description="IP地址" /> <Column Name="CreateTime" DataType="DateTime" Description="時間" /> <Column Name="Remark" DataType="String" Length="500" Description="詳細信息" /> </Columns> <Indexes> <Index Columns="Category" /> <Index Columns="CreateUserID" /> <Index Columns="CreateTime" /> </Indexes> </Table> <Table Name="UserOnline" Description="用戶在線" ConnName="Log"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="UserID" DataType="Int32" Description="用戶" /> <Column Name="Name" DataType="String" Master="True" Description="名稱" /> <Column Name="SessionID" DataType="String" Description="會話。Web的SessionID或Server的會話編號" /> <Column Name="Times" DataType="Int32" Description="次數" /> <Column Name="Page" DataType="String" Description="頁面" /> <Column Name="Status" DataType="String" Length="200" Description="狀態" /> <Column Name="OnlineTime" DataType="Int32" Description="在線時間。本次在線總時間,秒" /> <Column Name="CreateIP" DataType="String" Description="創建地址" /> <Column Name="CreateTime" DataType="DateTime" Description="創建時間" /> <Column Name="UpdateTime" DataType="DateTime" Description="修改時間" /> </Columns> <Indexes> <Index Columns="UserID" /> <Index Columns="SessionID" /> <Index Columns="CreateTime" /> </Indexes> </Table> <Table Name="VisitStat" Description="訪問統計" ConnName="Log"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" /> <Column Name="Level" DataType="Int32" Description="層級" Type="XCode.Statistics.StatLevels" /> <Column Name="Time" DataType="DateTime" Description="時間" /> <Column Name="Page" DataType="String" Nullable="False" Description="頁面" /> <Column Name="Title" DataType="String" Master="True" Description="標題" /> <Column Name="Times" DataType="Int32" Description="次數" /> <Column Name="Users" DataType="Int32" Description="用戶" /> <Column Name="IPs" DataType="Int32" Description="IP" /> <Column Name="Error" DataType="Int32" Description="錯誤" /> <Column Name="Cost" DataType="Int32" Description="耗時。毫秒" /> <Column Name="MaxCost" DataType="Int32" Description="最大耗時。毫秒" /> <Column Name="CreateTime" DataType="DateTime" Description="創建時間" /> <Column Name="UpdateTime" DataType="DateTime" Description="更新時間" /> <Column Name="Remark" DataType="String" Length="500" Description="詳細信息" /> </Columns> <Indexes> <Index Columns="Page,Level,Time" Unique="True" /> <Index Columns="Level,Time" /> </Indexes> </Table> </Tables>
真實項目開發中,一般數據層類庫項目為不同子模塊划分目錄,每個目錄有自己的Model.xml+Build.tt,負責本模塊的模型維護已經實體類生成。
頭部屬性解釋:
Output,輸出目錄
NameSpace,命名空間
ConnName,連接名,對應app.config/web.config中connectionStrings下的name
BaseEntity,基類,默認Entity,同一個子模塊也可以共用自己的泛型基類EntityBase
Tables中的這些屬性對本模型文件所有Table有效,各個Table上也可以指定這些屬性,以覆蓋全局設置
Table.Name 就是生成的實體類類名,如果實際表名不同,可用TableName指定表名。
Column.Name就是生成的實體類屬性名,如果實際字段名不同,可用ColumnName指定字段名。
字符串長度Length默認50,不建議小於50,-1表示最大ntext
其它字段不建議設置長度,特別不建議給Double和Decimal設置精度
字段Column只需要DataType指定.Net類型即可,反向工程會根據使用數據庫的不同而映射到不同數據庫類型。
如果不喜歡XCode推薦的數據庫類型,可在Column中通過RawType指定原始數據庫類型。
Column支持Type指定枚舉類型,建議是帶命名空間的全名。例如上面User表中Sex類型的字段就是枚舉SexKinds
Indexes內放置該表所有索引。
每一行Index為一組索引,Columns內指定索引所需要的字段(注意先后順序),Unique指定是否唯一索引。
!!XCode反向工程支持自動創建或刪除索引。
可以通過碼神工具/建模工具,從數據庫中導出數據表對應的模型文件;
也可以編碼通過DAL.Export導出模型文件;
魔方的系統管理數據庫頁面,也可以導出模型文件;
數據名字規范
模型文件的Table名將會生成實體類類名,Column字段名將會生成實體類屬性名,因此命名規范很重要。
- 名稱必須使用通俗易懂的英文單詞全拼,常用的縮略詞(如ID)除外
- 采用大駝峰命名,每個單詞首字母大寫,其它小寫,類型屬性名符合.Net規范
-
名稱必須簡潔明了,不要加多余的前綴(如表名前加tbl),字段名也不要加表名前綴
-
不得使用SQL關鍵字或C#關鍵字作為表名或字段名
-
使用數據庫常用類型,如Int32和String,大文本長度-1
-
給表和字段加上說明,作為文件名,以及生成代碼的注釋
-
每張表必須有唯一主鍵字段(建議自增ID)
-
主從表中,從表加關聯字段(主表名+主表主鍵名)。XCode會識別為主從關系,生成擴展屬性
-
每張表設置好索引,注意是否唯一。XCode會識別為索引,生成擴展查詢
數據類型規范
模型文件設計要求開發者有一點數據庫基礎,至少要能明確表、字段和索引的概念。
然而要求又遠比數據庫要低得多,因為咱們推崇極致簡單的原則。
類型 |
|
數據庫類型 |
推薦 |
備注 |
Int32 |
整數 |
int |
強烈 |
優先 |
String |
字符串 |
nvarchar(50) |
強烈 |
默認變長50 |
DateTime |
時間日期 |
datetime |
強烈 |
不建議純日期或時間 |
Boolean |
布爾型 |
bit |
強烈 |
MySql中建議tinyint替代枚舉來實現布爾型 |
Int64 |
長整型 |
long |
強烈 |
有可能超過21億的整數,選長整型 |
Decimal |
十進制 |
money |
慎用 |
高精度貨幣型時采用 |
Double |
雙精度 |
double |
慎用 |
特別慎用,避免浮點運算導致精度丟失 |
Int16 |
|
short |
禁用 |
由Int32替代 |
Byte |
|
tinyint |
禁用 |
由Int32替代 |
Single |
|
single |
禁用 |
由Double替代 |
常用字段推薦
為了便於開發,XCode默認優待以下字段:
<Column Name="CreateUser" DataType="String" Description="創建者" /> <Column Name="CreateUserID" DataType="Int32" Description="創建者" /> <Column Name="CreateTime" DataType="DateTime" Description="創建時間" /> <Column Name="CreateIP" DataType="String" Description="創建地址" /> <Column Name="UpdateUser" DataType="String" Description="更新者" /> <Column Name="UpdateUserID" DataType="Int32" Description="更新者" /> <Column Name="UpdateTime" DataType="DateTime" Description="更新時間" /> <Column Name="UpdateIP" DataType="String" Description="更新地址" />
時間組CreateTime/UpdateTime字段對應TimeModule,在新增或更新時自動賦值;
IP組CreateIP/UpdateIP字段對應IPModule,在Web新增或更新時自動賦值;
用戶組CreateUser(ID)/UpdateUser(ID)字段對應UserModule,在Web新增或更新時字段賦值;
一句話:用了這些字段,在Insert時自動給CreateAbc賦值,在Update時自動給UpdateAbc賦值!
系列教程
NewLife.XCode教程系列[2019版]
- 增刪改查入門。快速展現用法,代碼配置連接字符串
- 數據模型文件。建立表格字段和索引,名字以及數據類型規范,推薦字段(時間,用戶,IP)
- 實體類詳解。數據類業務類,泛型基類,接口
- 功能設置。連接字符串,調試開關,SQL日志,慢日志,參數化,執行超時。代碼與配置文件設置,連接字符串局部設置
- 反向工程。自動建立數據庫數據表
- 數據初始化。InitData寫入初始化數據
- 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)
- 臟數據。如何產生,怎么利用
- 增量累加。高並發統計
- 事務處理。單表和多表,不同連接,多種寫法
- 擴展屬性。多表關聯,Map映射
- 高級查詢。復雜條件,分頁,自定義擴展FieldItem,查總記錄數,查匯總統計
- 數據層緩存。Sql緩存,更新機制
- 實體緩存。全表整理緩存,更新機制
- 對象緩存。字典緩存,適用用戶等數據較多場景。
- 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存
- 實體工廠。元數據,通用處理程序
- 角色權限。Membership
- 導入導出。Xml,Json,二進制,網絡或文件
- 分表分庫。常見拆分邏輯
- 高級統計。聚合統計,分組統計
- 批量寫入。批量插入,批量Upsert,異步保存
- 實體隊列。寫入級緩存,提升性能。
- 備份同步。備份數據,恢復數據,同步數據
- 數據服務。提供RPC接口服務,遠程執行查詢,例如SQLite網絡版
- 大數據分析。ETL抽取,調度計算處理,結果持久化