2009-12-28 102 views
6

我正在将此作为一个社区wiki,因为我会欣赏人们的做法,而不一定是答案。枚举或表?

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

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

我想有容易获得这些选项通过枚举,但也想在数据库中提供文本值,因为我会报告文本值而不是ID。另外,由于它们是静态的,我不想调用数据库。

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

谢谢

回答

7

我认为枚举是一个坏主意。只要给出你显示的数据类型,它可能会改变。最好是在应用程序初始化时加载具有ID/Min/Max/Description字段的数据库表。

+0

这是一个例子来创建枚举,它也不会改变。无论如何,我喜欢你的方法,你会如何坚持整个应用程序的数据。是否有任何性能问题,99%的应用程序不需要数据? – 2009-12-28 17:49:18

+1

如果这些数据很少被访问,那么您可以将它保存在第一次请求数据时初始化的静态类(延迟初始化)。只要确保锁定在适当的位置,以便一次只有一个线程可以访问该数据。这将消除任何启动速度减慢。如果您不希望第一次访问数据时等待,您还可以将数据加载到低优先级的工作队列中,以便在闲置一两次时加载(或者在需要时立即加载) – Eclipse 2009-12-28 17:56:56

+2

如果它确实不会改变,并且您没有数据库,那么您可以将其存储在自定义节中的app.config文件中。 – 2009-12-28 21:45:05

1

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

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

0

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

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

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

SQL报告怎么样?如何使用仅枚举方法解决这个问题。 – 2009-12-28 17:46:22

+1

从DB初始化字典,很简单。如果枚举后面的数据类型是整数,则将其映射到数据库列很简单。正如Aaron指出的那样,许多ORM可以开箱即用。 – 2009-12-28 17:49:09

-1

使用枚举(代码)和DB texts-的GUI表示。

所以,如果你将永远有3选项,在DB使用枚举LowSalaryMiddleSalaryHighSalary,存储您的文本和对应于你的财产枚举值的GUI切换您的文本。

1

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

0

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

通过这种方式,您可以维护一些智能感知,但不会试图在数据库中的字符串值上使用Enum值。

我会提供的另一种解决方案:取消依赖这些值的逻辑并转移到基于表的逻辑。 (例如,如果每笔交易的税率不同,请将税率作为数据库中的列添加,而不是代码中的案例{})。

2

一种方法是编写一个格式,可以把你枚举成字符串表示:

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)); 

格式化可以推广的,以支持通过格式化字符串,多种类型,本地化等不同的格式。

+0

我认为他们不会理解这个想法。我不知道为什么,但有一个数据库表为这3个变量可以看到他们更好...... – serhio 2009-12-29 09:47:36

1

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

基本上我使用默认值核心查找数据的SQL脚本,用的ID从其他表FK参考,然后我用一个简单的T4模板来生成我枚举了C#。这样数据库就是高效的,规范化的并且正确地受到限制,而且我的c#实体不必处理ID(幻数)。

它简单快速,简单,并为我做的工作。

我使用EF4,但你不需要,可以使用这种方法与任何你用于实体的技术。

6

对于静态项目,我使用Enum和每个元素的[Description()]属性。 和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."); 
}