zoukankan      html  css  js  c++  java
  • 枚举——你是那温柔的陷阱吗

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

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

    如是就有了以下代码:

    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
    }

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

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

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

    示例效果如下:

    OK,一切问题解决

    示例下载地址:https://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

  • 相关阅读:
    SDN期末作业验收
    SDN第五次上机作业
    SDN第四次作业
    SDN第四次上机作业
    SDN第三次上机
    SDN第三次作业
    第二次SDN上机作业
    SDN第二次作业
    SDN第一次上机作业
    SDN第一次作业
  • 原文地址:https://www.cnblogs.com/Deper/p/1781087.html
Copyright © 2011-2022 走看看