可以从以下GitHub repository 克隆以下代码,用于测试修改后的 NorthWind 数据库,请参阅the script here。
- 代码是使用 C#9、.NET Core 5 编写的,只需稍加调整即可与早期版本的 .NET Framework 一起使用
- 核心代码灵感来自this post。
示例创建类
public class Contacts
{
[JsonProperty("ContactId")]
public int ContactId { get; set; }
[JsonProperty("FirstName")]
public string FirstName { get; set; }
[JsonProperty("LastName")]
public string LastName { get; set; }
[JsonProperty("ContactTypeIdentifier")]
public int? ContactTypeIdentifier { get; set; }
}
在 DataOperations 类中,从文本文件中读取查询以生成特定数据库中每个表的类文件。
从存储库代码运行代码
DataOperations.Server = ".\\SQLEXPRESS";
DataOperations.Database = "NorthWind2020";
DataOperations.OutputFolder = "Classes";
DataOperations.Create();
在您的项目中运行此代码时,请确保在与您的可执行文件相同的文件夹下创建一个名为 Classes 的文件夹。
DataOperations.cs
using System.Data;
using System.Data.SqlClient;
using System.IO;
namespace CreateClassesFromSqlServer
{
public class DataOperations
{
/// <summary>
/// SQL-Server name
/// </summary>
public static string Server { get; set; }
/// <summary>
/// Database in Server
/// </summary>
public static string Database { get; set; }
/// <summary>
/// Location to create classes
/// </summary>
public static string OutputFolder { get; set; }
/// <summary>
/// Iterate <see cref="Database"/> tables, create classes from
/// SQL in the file ClassQuery.txt
/// </summary>
public static void Create()
{
var classQuery = File.ReadAllText("ClassQuery.txt");
using var connection = new SqlConnection($"Server={Server};Database={Database};Integrated Security=true");
connection.Open();
var adapter = new SqlDataAdapter(
"SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
$"FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_TYPE = 'BASE TABLE') AND (TABLE_CATALOG = '{Database}') AND (TABLE_NAME != N'sysdiagrams') " +
"ORDER BY TABLE_NAME", connection);
DataTable table = new DataTable();
adapter.Fill(table);
foreach (DataRow row in table.Rows)
{
var tableName = row["TABLE_NAME"].ToString();
var fileName = tableName + ".cs";
string sql = $"declare @TableName sysname = '{tableName}'{classQuery}";
using var cmd = new SqlCommand(sql, connection);
string code = (string)cmd.ExecuteScalar();
if (File.Exists(Path.Combine(OutputFolder, fileName)))
{
File.Delete(Path.Combine(OutputFolder, fileName));
}
File.WriteAllText(Path.Combine(OutputFolder, fileName), code);
}
}
}
}
查询生成类文件
declare @Result varchar(max) = 'public class ' + @TableName + '
{'
select @Result = @Result + CHAR(13) + ' [JsonProperty("' + ColumnName + '")]
public ' + ColumnType + NullableSign + ' ' + ColumnName + ' { get; set; }
'
from
(
select
replace(col.name, ' ', '_') ColumnName,
column_id ColumnId,
case typ.name
when 'bigint' then 'long'
when 'binary' then 'byte[]'
when 'bit' then 'bool'
when 'char' then 'string'
when 'date' then 'DateTime'
when 'datetime' then 'DateTime'
when 'datetime2' then 'DateTime'
when 'datetimeoffset' then 'DateTimeOffset'
when 'decimal' then 'decimal'
when 'float' then 'double'
when 'image' then 'byte[]'
when 'int' then 'int'
when 'money' then 'decimal'
when 'nchar' then 'string'
when 'ntext' then 'string'
when 'numeric' then 'decimal'
when 'nvarchar' then 'string'
when 'real' then 'float'
when 'smalldatetime' then 'DateTime'
when 'smallint' then 'short'
when 'smallmoney' then 'decimal'
when 'text' then 'string'
when 'time' then 'TimeSpan'
when 'timestamp' then 'long'
when 'tinyint' then 'byte'
when 'uniqueidentifier' then 'Guid'
when 'varbinary' then 'byte[]'
when 'varchar' then 'string'
else 'UNKNOWN_' + typ.name
end ColumnType,
case
when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier')
then '?'
else ''
end NullableSign
from sys.columns col
join sys.types typ on
col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
where object_id = object_id(@TableName)
) t
order by ColumnId
set @Result = @Result + '}'
select @Result
重要
不保证代码适合所有情况,尚未针对所有可能的情况进行全面测试。