從資料表產生 C# 類別 (Generate C# POCO Class From SQL Server Table)
2022-12-04
筆記如何從資料表產生類別 Class,讓使用 ADO.NET 或者是 Dapper 等資料存取方式,不用再手動對照資料表格逐筆 prop
🙂
說明
使用 dotnet ef
第一種方式其實與 EntityFramework Database First 無異,就是利用 EntityFramework 能夠自動產生 Table 與 Class 對應來產生類別 Class。
第一次使用 add package
需要部份的下載時間,整個過程可以在 5 分鐘內完成。
產生出來的類別 Class 或包含 Table 以及 View 的對應,開發人員再根據需求從 Model 資料夾剪取需要的類別到專案即可。
dotnet tool install --global dotnet-ef
dotnet new console
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 6.0.11
dotnet add package Microsoft.EntityFrameworkCore.Design --version 6.0.11
dotnet ef dbcontext scaffold "Server=.;Database=Northwind;Trusted_Connection=True;"
Microsoft.EntityFrameworkCore.SqlServer -o Model --force
如果想要使用 GUI 的方式,也可以另起臨時專案使用 .NET Framework Database First 的方式建立,再循相同方式將產生出來的類別檔剪貼到開發中的專案。
ASP.NET MVC EntityFramework Model (Database First)
使用 TSQL 組合類別字串
參考 Brian Pedersen 於Create C# Class from SQL 的範例程式碼,結合 sp_MSforeachtable
一次取得所有資料表的類別 Class。
使用上的缺點是仍需逐各個類別去建立檔案,外加上剪貼藉由 TSQL 產生的程式碼,略不方便。
建立 temp Stored Procedures 用以處理資料表對照為類別。
DROP PROC IF EXISTS #GenerateClassFromTable
GO
CREATE PROC #GenerateClassFromTable
@tableName nvarchar(1024)
AS
DECLARE @Schema VARCHAR(MAX) = replace(replace(substring(@tableName, 0, charindex('.', @tableName)), '[', ''), ']', '')
DECLARE @Table VARCHAR(MAX) = replace(replace(substring(@tableName, charindex('.', @tableName) + 1, 128), '[', ''), ']', '')
DECLARE @result varchar(max) = ''
SET @result = @result + 'namespace ' + @Schema + CHAR(13) + '{' + CHAR(13)
SET @result = @result + ' public class ' + @Table + CHAR(13) + ' {' + CHAR(13)
SELECT @result = @result + ' public ' + DataType + ' ' + PropertyName + ' { get; set; } ' + CHAR(13)
FROM (SELECT
UPPER(left(c.COLUMN_NAME,1))+SUBSTRING(c.COLUMN_NAME,2,LEN(c.COLUMN_NAME)) AS PropertyName,
CASE c.DATA_TYPE
WHEN 'bigint' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'long?' ELSE 'long' END
WHEN 'binary' THEN 'Byte[]'
WHEN 'bit' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'bool?' ELSE 'bool' END
WHEN 'char' THEN 'string'
WHEN 'date' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END
WHEN 'datetime' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END
WHEN 'datetime2' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END
WHEN 'datetimeoffset' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'DateTimeOffset?' ELSE 'DateTimeOffset' END
WHEN 'decimal' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'decimal?' ELSE 'decimal' END
WHEN 'float' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'double?' ELSE 'double' END
WHEN 'image' THEN 'Byte[]'
WHEN 'int' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'int?' ELSE 'int' END
WHEN 'money' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'decimal?' ELSE 'decimal' END
WHEN 'nchar' THEN 'string'
WHEN 'ntext' THEN 'string'
WHEN 'numeric' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'decimal?' ELSE 'decimal' END
WHEN 'nvarchar' THEN 'string'
WHEN 'real' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'double?' ELSE 'double' END
WHEN 'smalldatetime' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END
WHEN 'smallint' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'short?' ELSE 'short' END
WHEN 'smallmoney' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'decimal?' ELSE 'decimal' END
WHEN 'text' THEN 'string'
WHEN 'time' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'TimeSpan?' ELSE 'TimeSpan' END
WHEN 'timestamp' THEN 'Byte[]'
WHEN 'tinyint' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'Byte?' ELSE 'Byte' END
WHEN 'uniqueidentifier' THEN CASE C.IS_NULLABLE WHEN 'YES' THEN 'Guid?' ELSE 'Guid' END
WHEN 'varbinary' THEN 'Byte[]'
WHEN 'varchar' THEN 'string'
ELSE 'Object'
END AS DataType, c.ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = @Table
AND ISNULL(@Schema, c.TABLE_SCHEMA) = c.TABLE_SCHEMA) t
ORDER BY t.ORDINAL_POSITION
SET @result = @result + ' }' + CHAR(13)
SET @result = @result + '}'
PRINT @result
執行指令取得類別。
SELECT * FROM sys.tables
EXEC sp_MSforeachtable 'EXEC #GenerateClassFromTable "?"'
GO
範例成果:
namespace Dbo
{
public class Products
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public int? SupplierID { get; set; }
public int? CategoryID { get; set; }
public string QuantityPerUnit { get; set; }
public decimal? UnitPrice { get; set; }
public short? UnitsInStock { get; set; }
public short? UnitsOnOrder { get; set; }
public short? ReorderLevel { get; set; }
public bool Discontinued { get; set; }
}
}
Online Tools
sql2object 利用 Data 以及 Header 推測對應的類別 Class,畢竟是推測的可能發現不正確的型別對照。
CodVerter 藉由提供 SQL Create 指令,對照產生類別 Class。