从数据库查找表创建枚举






4.70/5 (9投票s)
使用 T4 模板可以轻松地一键同步代码中的枚举和数据库值
在使用数据库开发代码时,我们通常需要在代码中使用查找表中的一些值,并将它们用于比较或设置某些属性。
例如,如果您在代码中使用以下行
if(Car.Car_Type == 5){...
首先,没有人会理解数字 -5 的含义,如果我们把数据库中的值从 5 改成其他值,就会出现一个 bug。
所以正确的方法是使用枚举
if(Car.Car_Type == (byte)CarTypesEnum.SmallCars ){...
问题在于当数据库值发生变化时,对这个枚举的维护很困难。这就是 T4 模板的作用
如果您使用 Entity Framework,您可以在实体中生成枚举属性,以避免在条件中进行强制转换(请参阅这个提示,这是一个开始编写您自己的代码的点)
背景
所以,我需要从查找表中创建枚举。我找到了一些解决方案(例如 这个链接和 这个链接),包括一些 T4 解决方案,但它们都有一些问题:它们不支持非英语语言,并且它们需要在数据库表列名上进行一些更改。
我的 T4 模板具有这些优势
- 在枚举描述列中使用非英语语言的值,就我而言,查找表描述是用希伯来语写的,我绝对不想在我的枚举代码中使用一些希伯来语值。
- 无需编写需要生成的枚举表的硬编码名称。
- 无需更改表中的列名。
- 代码和数据库值之间轻松的一键同步。
- 对插入和使用此模板的代码进行细微更改。
解决方案
您需要添加一些、修复名称、在您的查找表中添加列并填充,在此新列中,枚举值,然后运行模板,所有枚举都将被创建。
例如
更改前的表格
Phone_Type_Id | 描述 | Some_Column_Name | Some_Column_Name2 |
1 | 三星 | 一些值 | 一些值 |
我们需要将其更改为
Phone_Type_Id | 描述 | Some_Column_Name | Some_Column_Name2 | Enum_Desc |
1 | 三星 | 一些值 | 一些值 | 三星 |
Using the Code
要将模板插入到您的项目中,您需要按照以下步骤操作
在 .NET 解决方案中
- 打开模板(.tt 扩展名)并将连接字符串设置为数据库
//Database connection string var connectionString = "data source=localhost;initial catalog=EF_Extention_Sample;integrated security=True;multipleactiveresultsets=True;";
- 设置指示表是枚举表的列名
//Enum value column name: var enumDescriptionColumnName = "Enum_Description";
- 设置枚举的命名空间
//Enum namespace var enumNameSpace = "MyNamespace";
在数据库中
- 将列(在第 2 节中)添加到数据库中所有需要生成枚举的表中。
- 在新列 [Enum_Description] 中插入枚举描述值,用于所有枚举表。如果 [Enum_Description] 列的值为 null,则不会在枚举中生成查找表行的值(这允许您仅将相关行插入到枚举中)。
最后,返回到模板文件,右键单击 -> 运行自定义工具 - 这将生成枚举。
每当您需要同步数据库值和代码时,执行此最后一步。
模板
创建数据库枚举的步骤是
我选择带有 [Enum_Column_Name
] 的所有表
command.CommandText = string.Format(@"SELECT DISTINCT t.NAME
FROM SYS.tables as t
INNER JOIN SYS.columns AS c ON t.object_id = c.object_id
AND c.name = '{0}'",enumDescriptionColumnName);
对于 SELECT 结果中的每个表,我创建一个枚举。
然后,在每个查找表的值上运行以填充枚举值。
* 我假设查找表中的第一列是表的主键。
//Start write enum file:
#>
namespace <#=enumNameSpace#>
{
public enum <#=enumName#>Enum
{
<#
command.CommandText = string.Format("SELECT * FROM {0}",codeGenerationTools.Escape(tableName));
var columnReader = command.ExecuteReader();
while (columnReader.Read())
{
//Fill only the values that the field "enumDescriptionColumnName" have value
if(!string.IsNullOrEmpty(columnReader[enumDescriptionColumnName].ToString().Trim()))
{
#> <#=columnReader[enumDescriptionColumnName].ToString()#> = <#=columnReader[0].ToString()#>,
<# }
}#>
}
}
<#
有关 T4 模板和 Entity Framework 使用的更多信息,您可以在这些链接中查看