枚举——你是那温柔的陷阱吗

      最近在园子里看了两篇关于枚举的文章《小心枚举陷阱》和《温柔的枚举陷阱》,说的都是一个问题:前台绑定枚举,数据库中存储枚举的值,当枚举更新后,数据库中的值却没有更新,于是引起了一堆数据不对应的问题。

  在系统中,我们肯定都遇到过用枚举来储存数据的情况,如下图,需要显示的是学历,但学历这东西毕竟不是经常改,所以就用枚举吧,放在数据库中,还要新建一张表,还要左联,太麻烦。

2010072011083915.png

如是就有了以下代码:

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,别人一看就知道大学,但前台上,我要显示的是“大学”两个汉字,如下:

  2010072011083915.png

  于是我就编写了一个枚举的通用类:

  

ContractedBlock.gif ExpandedBlockStart.gif 枚举操作类
 
   
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;
}
}

}

 

 

 枚举申明时如下:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
public enum EStueType
{
[EnumDescription(
" 小学 " )]
Primaryschool,
[EnumDescription(
" 初中 " )]
JuniorHighSchool,
[EnumDescription(
" 大学 " )]
HighSchool,
[EnumDescription(
" 大学 " )]
University
}

 

 

 前台绑定时:EnumUtils<EStueType>.BindListControl(this.comboBox1); 

获得绑定值时(枚举类型): EnumUtils<EStueType>.GetEnum(this.comboBox1.SelectedValue.ToString());;

获得显示值时(枚举显示名称):EnumUtils<EStueType>.GetText(EStueType.HighSchool);

 

示例效果如下:

2010072014363038.png

 

 

OK,一切问题解决

 

示例下载地址:http://files.cnblogs.com/Deper/%e6%9e%9a%e4%b8%be%e6%93%8d%e4%bd%9c%e7%b1%bb%e7%a4%ba%e4%be%8b.rar

转载于:https://www.cnblogs.com/Deper/archive/2010/07/20/1781087.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值