在数据库中存储Enum的最佳方法
使用C#和Visual Studio和MySQL数据连接器将Enum存储在数据库中的最佳方法是什么?
我将要创build一个超过100个枚举的新项目,其中大多数将不得不存储在数据库中。 为每一个创build转换器将是一个漫长的过程,因此,我想知道如果视觉工作室或有人有任何方法,我没有听说过。
[Required] public virtual int PhoneTypeId { get { return (int)this.PhoneType; } set { PhoneType = (PhoneTypes)value; } } [EnumDataType(typeof(PhoneTypes))] public PhoneTypes PhoneType { get; set; } public enum PhoneTypes { Mobile = 0, Home = 1, Work = 2, Fax = 3, Other = 4 }
奇迹般有效! 不需要在代码中转换(int)Enum或(Enum)int。 只需使用enum和ef代码,将为您保存int。 ps:“[EnumDataType(typeof(PhoneTypes))]”属性不是必需的,只是额外的,如果你想要的附加function。
或者你可以这样做:
[Required] public virtual int PhoneTypeId { get; set; } [EnumDataType(typeof(PhoneTypes))] public PhoneTypes PhoneType { get { return (PhoneTypes)this.PhoneTypeId; } set { this.PhoneTypeId = (int)value; } }
我们存储我们的整数或长整数,然后我们可以来回投射它们。 可能不是最强大的解决scheme,但那是我们所做的。
我们使用的是键入的数据集,例如:
eunum BlockTreatmentType { All = 0 }; // blockTreatmentType is an int property blockRow.blockTreatmentType = (int)BlockTreatmentType.All; BlockTreatmentType btt = (BlockTreatmentType)blockRow.blocktreatmenttype;
最后,你将需要一个很好的方式来处理重复的编码任务,如枚举转换器。 您可以使用代码生成器(如MyGeneration或CodeSmith) ,或者使用像nHibernate这样的ORM映射器来处理所有的事情。
至于结构…有数百个枚举,我会首先考虑尝试组织数据到一个单一的表,可能看起来像这样:(pseudo sql)
MyEnumTable( EnumType as int, EnumId as int PK, EnumValue as int )
这将允许您将枚举信息存储在一个表中。 EnumType也可以是定义不同枚举的表的外键。
你的商业对象将通过EnumId链接到这个表。 枚举types仅用于UI中的组织和过滤。 利用所有这些当然取决于你的代码结构和问题领域。
顺便说一句,在这种情况下,你会想在EnumType上设置聚簇索引,而不是保留在PKey上创build的默认簇idx。
有些事情你应该考虑。
枚举列将被其他应用程序直接使用,例如报告。 这将限制枚举以整数格式存储的可能性,因为除非报表具有自定义逻辑,否则该值在报表中将没有任何意义。
国际需求是什么? 如果仅支持一种语言,则可以将枚举保存为文本,并创build一个帮助器方法以从描述string进行转换。 你可以使用[DescriptionAttribute]
来进行转换,也可以通过search来find转换的方法。
另一方面,如果您需要支持多种语言和外部应用程序访问您的数据,则可以开始考虑枚举是否真的是答案。 如果场景更复杂,可以考虑其他选项,如查找表。
枚举是非常好的,当它们自己包含在代码中时…当它们跨越边界时,事情往往会变得有点混乱。
更新:
您可以使用Enum.ToObject
方法从一个整数转换。 这意味着你知道转换时枚举的types。 如果你想完全通用,你需要将枚举的types和数据库中的值一起存储。 您可以创build数据字典支持表来告诉您哪些列是枚举以及它们是什么types。
如果你想存储所有的枚举值,你可以尝试下面的表来存储枚举和它们的成员,以及代码片段来添加这些值。 我只是在安装的时候这样做,但是,因为这些值将永远不会改变,直到你重新编译!
数据库表:
create table EnumStore ( EnumKey int NOT NULL identity primary key, EnumName varchar(100) ); GO create table EnumMember ( EnumMemberKey int NOT NULL identity primary key, EnumKey int NOT NULL, EnumMemberValue int, EnumMemberName varchar(100) ); GO --add code to create foreign key between tables, and index on EnumName, EnumMemberValue, and EnumMemberName
C#代码片段:
void StoreEnum<T>() where T: Enum { Type enumToStore = typeof(T); string enumName = enumToStore.Name; int enumKey = DataAccessLayer.CreateEnum(enumName); foreach (int enumMemberValue in Enum.GetValues(enumToStore)) { string enumMemberName = Enum.GetName(enumToStore, enumMemberValue); DataAccessLayer.AddEnumMember(enumKey, enumMemberValue, enumMemberName); } }
如果您需要在枚举字段的DBstring值中存储,最好像下面的show一样。 例如,如果您正在使用不支持enum字段的SQLite,则可能需要使用它。
[Required] public string PhoneTypeAsString { get { return this.PhoneType.ToString(); } set { PhoneType = (PhoneTypes)Enum.Parse( typeof(PhoneTypes), value, true); } } public PhoneTypes PhoneType{get; set;}; public enum PhoneTypes { Mobile = 0, Home = 1, Work = 2, Fax = 3, Other = 4 }
我不确定它是否是最灵活的,但你可以简单地存储它们的string版本。 这当然是可读的,但可能难以维护。 枚举可以很容易地从string转换回来:
public enum TestEnum { MyFirstEnum, MySecondEnum } static void TestEnums() { string str = TestEnum.MyFirstEnum.ToString(); Console.WriteLine( "Enum = {0}", str ); TestEnum e = (TestEnum)Enum.Parse( typeof( TestEnum ), "MySecondEnum", true ); Console.WriteLine( "Enum = {0}", e ); }
为什么不尝试从数据库中分离枚举? 我发现这篇文章是一个伟大的参考,而在类似的工作:
http://stevesmithblog.com/blog/reducing-sql-lookup-tables-and-function-properties-in-nhibernate/
无论你使用什么数据库,它的思想都应该适用。 例如,在MySQL中,您可以使用“enum”数据types来强制遵守您的编码枚举:
http://dev.mysql.com/doc/refman/5.0/en/enum.html
干杯