【发布时间】:2009-12-28 17:40:51
【问题描述】:
我将其设为社区 wiki,因为我会欣赏人们的方法,但不一定是答案。
我的情况是我有很多查找类型的数据字段,这些字段不会改变。一个例子是:
年薪
选项:0 - 25K
选项:25K - 100K
选项:100K +
我希望通过枚举轻松获得这些选项,但也希望数据库中可用的文本值,因为我将报告文本值而不是 ID。另外,由于它们是静态的,我不想调用数据库。
我想在枚举和表格中复制这个,但想听听一些替代的想法。
谢谢
【问题讨论】:
我将其设为社区 wiki,因为我会欣赏人们的方法,但不一定是答案。
我的情况是我有很多查找类型的数据字段,这些字段不会改变。一个例子是:
年薪
选项:0 - 25K
选项:25K - 100K
选项:100K +
我希望通过枚举轻松获得这些选项,但也希望数据库中可用的文本值,因为我将报告文本值而不是 ID。另外,由于它们是静态的,我不想调用数据库。
我想在枚举和表格中复制这个,但想听听一些替代的想法。
谢谢
【问题讨论】:
我认为枚举是个坏主意。鉴于您显示的数据类型,它可能会发生变化。最好有一个数据库表,其中包含您在应用初始化时加载的 ID/Min/Max/Description 字段。
【讨论】:
对于静态项目,我对每个元素使用带有 [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.");
}
【讨论】:
一种方法是编写一个可以将枚举转换为字符串表示形式的格式化程序:
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));
格式化程序可以通过格式化字符串、多种类型、本地化等扩展为支持不同的格式。
【讨论】:
我两个都用。在 Linq to SQL 和 EF 中,您只需将列属性设为枚举类型。在其他框架中,您通常可以以某种方式将列映射到枚举属性。您仍然可以在数据库中拥有一个包含有效枚举的主键表。
您也可以在数据库中使用 CHECK 约束来执行此操作,但这往往会将您的数据绑定到您的应用程序 - 单独查看数据库的人不一定知道每个值的含义。因此我更喜欢混合表/枚举。
【讨论】:
首先确保这些数据确实是静态的。如果有任何变化,您将不得不重新编译和重新部署。
如果数据真的是静态的,我会走枚举路线。您可以创建一个 YearlySalaryEnum 来保存所有值。对于字符串表示,我将使用带有字符串值和YearlySalaryEnum 作为键的字典。字典可以作为静态类中的静态实例保存。用法与 (C#) 类似:
string highSalary = StaticValues.Salaries[YearlySalaryEnum.High];
【讨论】:
同时使用,你应该调查 CodeDOM。使用它,您可以编写代码生成例程,允许编译过程通过读取数据库自动生成其中包含这些枚举的程序集或类。这样你就可以让数据库驱动,但你不会在每次访问枚举实例时都调用数据库......
【讨论】:
在这里查看我的建议How to work with Enums in Entity Framework?
基本上我对核心查找数据使用默认值 sql 脚本,使用 ID 用于来自其他表的 FK 引用,然后我使用一个简单的 T4 模板为 c# 生成我的枚举。这样,数据库是高效的、规范化的和正确约束的,我的 c# 实体不必处理 ID(幻数)。
它简单快捷,轻松,为我完成了这项工作。
我使用 EF4,但您不需要,可以将此方法与您用于实体的任何技术一起使用。
【讨论】:
由于 C# 不允许带有字符串值的枚举,所以我建议使用一些静态字符串的结构。
这样,您可以维护一些 Intellisense,但无需尝试在数据库中的字符串值上硬塞一个 Enum 值。
我将提供的另一种解决方案:删除依赖于这些值的逻辑并转移到基于表的逻辑。 (例如,如果每个批次的税率不同,则将税率添加为数据库中的列,而不是代码中的 case {}。
【讨论】:
使用 both 枚举(用于代码)和 DB 文本 - 用于 GUI 演示。
因此,如果您始终有 3 个选项,请使用枚举 LowSalary、MiddleSalary 和 HighSalary,将您的文本存储在数据库中,并在 GUI 中根据您的属性枚举值切换文本。
【讨论】: