65.9K
CodeProject 正在变化。 阅读更多。
Home

从数据库查找表创建枚举

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (9投票s)

2012年7月13日

CPOL

3分钟阅读

viewsIcon

106840

downloadIcon

3513

使用 T4 模板可以轻松地一键同步代码中的枚举和数据库值

在使用数据库开发代码时,我们通常需要在代码中使用查找表中的一些值,并将它们用于比较或设置某些属性。

例如,如果您在代码中使用以下行

if(Car.Car_Type == 5){...

首先,没有人会理解数字 -5 的含义,如果我们把数据库中的值从 5 改成其他值,就会出现一个 bug

所以正确的方法是使用枚举

 if(Car.Car_Type ==  (byte)CarTypesEnum.SmallCars ){...

问题在于当数据库值发生变化时,对这个枚举的维护很困难。这就是 T4 模板的作用

如果您使用 Entity Framework,您可以在实体中生成枚举属性,以避免在条件中进行强制转换(请参阅这个提示,这是一个开始编写您自己的代码的点)

背景

所以,我需要从查找表中创建枚举。我找到了一些解决方案(例如 这个链接和 这个链接),包括一些 T4 解决方案,但它们都有一些问题:它们不支持非英语语言,并且它们需要在数据库表列名上进行一些更改。

我的 T4 模板具有这些优势

  1. 在枚举描述列中使用非英语语言的值,就我而言,查找表描述是用希伯来语写的,我绝对不想在我的枚举代码中使用一些希伯来语值。
  2. 无需编写需要生成的枚举表的硬编码名称。
  3. 无需更改表中的列名。
  4. 代码和数据库值之间轻松的一键同步。
  5. 对插入和使用此模板的代码进行细微更改。

解决方案

您需要添加一些、修复名称、在您的查找表中添加列并填充,在此新列中,枚举值,然后运行模板,所有枚举都将被创建。

例如

更改前的表格

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 解决方案中

  1. 打开模板(.tt 扩展名)并将连接字符串设置为数据库
    //Database connection string
    var connectionString = "data source=localhost;initial catalog=EF_Extention_Sample;integrated security=True;multipleactiveresultsets=True;";
  2. 设置指示表是枚举表的列名
     //Enum value column name:
    var enumDescriptionColumnName = "Enum_Description";
  3. 设置枚举的命名空间
    //Enum namespace
    var enumNameSpace = "MyNamespace";

    在数据库中

  4. 将列(在第 2 节中)添加到数据库中所有需要生成枚举的表中。
  5. 在新列 [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 使用的更多信息,您可以在这些链接中查看

© . All rights reserved.