【问题标题】:Enums or Tables?枚举还是表格?
【发布时间】:2009-12-28 17:40:51
【问题描述】:

我将其设为社区 wiki,因为我会欣赏人们的方法,但不一定是答案。

我的情况是我有很多查找类型的数据字段,这些字段不会改变。一个例子是:

年薪
选项:0 - 25K
选项:25K - 100K
选项:100K +

我希望通过枚举轻松获得这些选项,但也希望数据库中可用的文本值,因为我将报告文本值而不是 ID。另外,由于它们是静态的,我不想调用数据库。

我想在枚举和表格中复制这个,但想听听一些替代的想法。

谢谢

【问题讨论】:

    标签: c# enums


    【解决方案1】:

    我认为枚举是个坏主意。鉴于您显示的数据类型,它可能会发生变化。最好有一个数据库表,其中包含您在应用初始化时加载的 ID/Min/Max/Description 字段。

    【讨论】:

    • 这是一个例子,它不会改变。无论如何,我喜欢您的方法,您将如何在整个应用程序中保留数据。由于 99% 的应用不需要数据,是否会出现性能问题?
    • 如果这个数据很少被访问,你可以把它保存在一个静态类中,在你第一次请求数据时初始化(延迟初始化)。只需确保锁定到位,以便一次只有一个线程可以访问该数据。这将消除任何启动减速。如果您不想在第一次访问数据时等待,您还可以将加载数据添加到低优先级工作队列中,以便在空闲一两分钟时加载(或者如果更早需要,则立即加载)
    • 如果它真的不会改变并且您没有数据库,您可以将其存储在您的 app.config 文件的自定义部分中。
    • 真的,我不明白这里的 OR 想法。如果 texts 发生变化,它应该在 DB 中,但是当您从 DB 加载它时,您会将它与 枚举。这是在这种情况下使用的枚举意义。
    【解决方案2】:

    对于静态项目,我对每个元素使用带有 [Description()] 属性的 Enum。 和 T4 模板,用于在构建时(或任何时候)重新生成枚举

    public enum EnumSalary
        {
            [Description("0 - 25K")] Low,
            [Description("25K - 100K")] Mid,
            [Description("100K+")] High
        }
    

    并像使用它一样

    string str = EnumSalary.Mid.Description()
    

    附:还为 System.Enum 创建了扩展

    public static string Description(this Enum value) {
        FieldInfo fi = value.GetType().GetField(value.ToString());
        var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false );
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
    

    并通过描述反向创建枚举

    public static TEnum ToDescriptionEnum<TEnum>(this string description)
    {
        Type enumType = typeof(TEnum);
        foreach (string name in Enum.GetNames(enumType))
        {
            var enValue = Enum.Parse(enumType, name);
            if (Description((Enum)enValue).Equals(description)) {
                return (TEnum) enValue;
            }
        }
        throw new TargetException("The string is not a description or value of the specified enum.");
    }
    

    【讨论】:

      【解决方案3】:

      一种方法是编写一个可以将枚举转换为字符串表示形式的格式化程序:

      public class SalaryFormatter : IFormatProvider, ICustomFormatter
      {
          public object GetFormat(Type formatType)
          {
               return (formatType == typeof(ICustomFormatter)) ? new
               SalaryFormatter () : null;
          }
      
          public string Format(string format, object o, IFormatProvider formatProvider)
          {
              if (o.GetType().Equals(typeof(Salary)))
              {
                  return o.ToString();
      
                  Salary salary = (Salary)o;
                  switch (salary)
                  {
                      case Salary.Low:
                           return "0 - 25K";
                      case Salary.Mid:
                           return "25K - 100K";
                      case Salary.High:
                           return "100K+";
                      default:
                           return salary.ToString();
                  }
              }
      
          return o.ToString();
          }
      }
      

      您可以像使用任何其他格式化程序一样使用格式化程序:

      Console.WriteLine(String.Format(new SalaryFormatter(), "Salary: {0}", salary));
      

      格式化程序可以通过格式化字符串、多种类型、本地化等扩展为支持不同的格式。

      【讨论】:

      • 我认为他们不会欣赏这个想法。我不知道为什么,但是他们认为这 3 个变量的数据库表更好......
      【解决方案4】:

      我两个都用。在 Linq to SQL 和 EF 中,您只需将列属性设为枚举类型。在其他框架中,您通常可以以某种方式将列映射到枚举属性。您仍然可以在数据库中拥有一个包含有效枚举的主键表。

      您也可以在数据库中使用 CHECK 约束来执行此操作,但这往往会将您的数据绑定到您的应用程序 - 单独查看数据库的人不一定知道每个值的含义。因此我更喜欢混合表/枚举。

      【讨论】:

        【解决方案5】:

        首先确保这些数据确实是静态的。如果有任何变化,您将不得不重新编译和重新部署。

        如果数据真的是静态的,我会走枚举路线。您可以创建一个 YearlySalaryEnum 来保存所有值。对于字符串表示,我将使用带有字符串值和YearlySalaryEnum 作为键的字典。字典可以作为静态类中的静态实例保存。用法与 (C#) 类似:

        string highSalary = StaticValues.Salaries[YearlySalaryEnum.High];
        

        【讨论】:

        • SQL 报告呢?如何使用仅枚举方法解决。
        • 从数据库初始化字典,很简单。如果枚举后面的数据类型是整数,则将其映射到 db 列很简单。正如 Aaron 所指出的,许多 ORM 可以开箱即用。
        【解决方案6】:

        同时使用,你应该调查 CodeDOM。使用它,您可以编写代码生成例程,允许编译过程通过读取数据库自动生成其中包含这些枚举的程序集或类。这样你就可以让数据库驱动,但你不会在每次访问枚举实例时都调用数据库......

        【讨论】:

          【解决方案7】:

          在这里查看我的建议How to work with Enums in Entity Framework?

          基本上我对核心查找数据使用默认值 sql 脚本,使用 ID 用于来自其他表的 FK 引用,然后我使用一个简单的 T4 模板为 c# 生成我的枚举。这样,数据库是高效的、规范化的和正确约束的,我的 c# 实体不必处理 ID(幻数)。

          它简单快捷,轻松,为​​我完成了这项工作。

          我使用 EF4,但您不需要,可以将此方法与您用于实体的任何技术一起使用。

          【讨论】:

            【解决方案8】:

            由于 C# 不允许带有字符串值的枚举,所以我建议使用一些静态字符串的结构。

            这样,您可以维护一些 Intellisense,但无需尝试在数据库中的字符串值上硬塞一个 Enum 值。

            我将提供的另一种解决方案:删除依赖于这些值的逻辑并转移到基于表的逻辑。 (例如,如果每个批次的税率不同,则将税率添加为数据库中的列,而不是代码中的 case {}。

            【讨论】:

              【解决方案9】:

              使用 both 枚举(用于代码)和 DB 文本 - 用于 GUI 演示。

              因此,如果您始终有 3 个选项,请使用枚举 LowSalaryMiddleSalaryHighSalary,将您的文本存储在数据库中,并在 GUI 中根据您的属性枚举值切换文本。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-11-23
                • 1970-01-01
                • 2013-01-11
                相关资源
                最近更新 更多