飞鸽传书:浅谈枚举
枚举——你是那温柔的陷阱吗?最近在园子里看了两篇关于枚举的文章《小心枚举陷阱》和《温柔的枚举陷阱》,说的都是一个问题:前台绑定枚举,数据库中存储枚举的值,当枚举更新后,数据库中的值却没有更新,于是引起了一堆数据不对应的问题。
在系统中,我们肯定都遇到过用枚举来储存数据的情况,如下图,需要显示的是学历,但学历这东西毕竟不是经常改,所以就用枚举吧,放在数据库中,还要新建一张表,还要左联,太麻烦。
如是就有了以下代码:
view sourceprint?1 public enum EStueType { 小学, 中学, 大学, }
然后数据库中存储的就是0、1、2,用来分别表示小学、中学、大学。
但后来,新的需求来了,需要将中学变为初中和高中。有人想当然,直接将“中学”改成“初中”,然后再在“初中”和“大学”之间加一个“高中”,编译无误,OK,挂到服务器上了。
后来客户反应,噫?我以前不是填的大学吗?现在怎么变成高中生了啊?管理员拿个VS编译半天,终于发现,原来添加了一个“高中”后,“高中”的值变为2 了,也就是说数据库中原来的所有学历为2(以前表示的是大学生),现在都变成高中生了。哎,都是这温柔的枚举惹的祸啊,于是开始摈弃枚举。
解决这个问题常用的做法有两种:
1.新建一张表,专门用来存储学历
2.接着用那温柔的枚举。
第一种方法很好的解决了这个问题,但问题在于会在数据库中新建表,并且是一张更新不多的表,另一个问题是如果数据量大时,左联会影响性能。
第二种方法就需要我们很好的解决枚举的问题了,下面我就讲我用枚举时的做法。
用枚举时我们也有两种做法:第一:将枚举显示赋值:如下:
public enum EStueType
{
小学=0,
中学=1,
大学=2,
}
OK,你要新加一个高中对吧,难不到我:
public enum EStueType
{
小学=0,
初中=1,
高中=3,
大学=2,
}
新问题:dbo查数据:select * from [表名],然后发现用户的学历这儿,一夫0123想当然的他认为
0代表小学
1代表初中
2代表高中
3代表大学
OK,他接下的操作就极具危险性了:他要对所有的大学生进行一次“婚前性教育培训课”,结果...........
于是,我们想着,要不我们数据库中直接存储枚名称,而不是值,也就是表中学历字段直接存储如“大学”。
嗯,这个办法不错,问题都解决了。
但好像我们学编程的第一节课老师就说了:不要用中文。有两个原因:
1.中文占用更多的数据库空间
2.中文编程总让人感觉不是那么专业飞鸽传书
于是我就想:如何实现这样的效果呢:数据库中只存储英文名称:如University,别人一看就知道大学,但前台上,我要显示的是“大学”两个汉字,飞鸽传书如下:
于是我就编写了一个枚举的通用类:
枚举操作类
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Reflection;using System.Data;using System.Windows.Forms;namespace WindowsFormsApplication1{ public class EnumUtils<Tenum> { public static DataTable GetAllEnums() { Type t = typeof(Tenum); FieldInfo[] fieldInfoList = t.GetFields(); DataTable dt = new DataTable(); dt.Columns.Add("Text", typeof(string)); dt.Columns.Add("Value", typeof(string)); foreach (FieldInfo tField in fieldInfoList) { if (!tField.IsSpecialName) { DataRow dr = dt.NewRow(); dr["Value"] = tField.Name; EnumDescriptionAttribute[] enumAttributelist = (EnumDescriptionAttribute[])tField.GetCustomAttributes(typeof(EnumDescriptionAttribute), false); if (enumAttributelist != null && enumAttributelist.Length > 0) { dr["Text"] = enumAttributelist[0].Description; } else { dr["Text"] = tField.Name; } dt.Rows.Add(dr); } } return dt; } public static string GetText(Tenum enumInstance) { Type t = typeof(Tenum); FieldInfo[] fieldInfoList = t.GetFields(); string strReturn = string.Empty; foreach (FieldInfo tField in fieldInfoList) { if (!tField.IsSpecialName && tField.Name.ToLower() == enumInstance.ToString().ToLower()) { EnumDescriptionAttribute[] enumAttributelist = (EnumDescriptionAttribute[])tField.GetCustomAttributes(typeof(EnumDescriptionAttribute), false); if (enumAttributelist != null && enumAttributelist.Length > 0) { strReturn = enumAttributelist[0].Description; break; } } } return strReturn; } public static string GetValue(Tenum enumInstance) { Type t = typeof(Tenum); FieldInfo[] fieldInfoList = t.GetFields(); string strReturn = string.Empty; foreach (FieldInfo tField in fieldInfoList) { if (!tField.IsSpecialName && tField.Name.ToLower() == enumInstance.ToString().ToLower()) { strReturn = tField.Name; break; } } return strReturn; } public static Tenum GetEnum(string Value) { Type t = typeof(Tenum); FieldInfo field = t.GetField(Value); return (Tenum)System.Enum.Parse(t, Value); } public static void BindListControl(ListControl listControl) { listControl.DisplayMember = "Text"; listControl.ValueMember = "Value"; listControl.DataSource = GetAllEnums(); } } [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, AllowMultiple = false)] public class EnumDescriptionAttribute : Attribute { private string description; public string Description { get { return this.description; } } public EnumDescriptionAttribute(string description) : base() { this.description = description; } }}
飞鸽传书枚举申明时如下:
代码
public enum EStueType { [EnumDescription("小学")] Primaryschool, [EnumDescription("初中")] JuniorHighSchool, [EnumDescription("大学")] HighSchool, [EnumDescription("大学")] University }
飞鸽传书:http://www.freeeim.com/
前台绑定时:EnumUtils<EStueType>.BindListControl(this.comboBox1);
获得绑定值时(枚举类型): EnumUtils<EStueType>.GetEnum(this.comboBox1.SelectedValue.ToString());;
获得显示值时(枚举显示名称):EnumUtils<EStueType>.GetText(EStueType.HighSchool);
示例效果如下:
OK,一切问题解决