C# 枚举还是表?
我把它变成一个社区维基,因为我会欣赏人们的方法,而不一定是答案 我的情况是,我有很多查找类型的数据字段,这些字段不会改变。例如: 年薪C# 枚举还是表?,c#,enums,C#,Enums,我把它变成一个社区维基,因为我会欣赏人们的方法,而不一定是答案 我的情况是,我有很多查找类型的数据字段,这些字段不会改变。例如: 年薪 选项:0-25K 选项:25K-100K 选项:10万+ 我希望这些选项可以通过枚举轻松获得,但也希望数据库中的文本值可用,因为我将报告文本值而不是ID。此外,由于它们是静态的,我不希望调用数据库 我想在枚举和表中复制这个,但想听听其他想法 谢谢我认为枚举是个坏主意。仅考虑到您显示的数据类型,它可能会发生更改。最好有一个带有ID/Min/Max/Descript
选项:0-25K
选项:25K-100K
选项:10万+ 我希望这些选项可以通过枚举轻松获得,但也希望数据库中的文本值可用,因为我将报告文本值而不是ID。此外,由于它们是静态的,我不希望调用数据库 我想在枚举和表中复制这个,但想听听其他想法
谢谢我认为枚举是个坏主意。仅考虑到您显示的数据类型,它可能会发生更改。最好有一个带有ID/Min/Max/Description字段的数据库表,在应用程序初始化时加载这些字段。我同时使用这两个字段。在LINQtoSQL和EF中,只需将列属性设置为枚举类型。在其他框架中,通常可以以某种方式将列映射到枚举属性。数据库中仍然可以有一个包含有效枚举的主键表
您也可以通过数据库中的检查约束来实现这一点,但这往往会将您的数据与应用程序绑定在一起—仅查看数据库的人不一定知道每个值的含义。因此,我更喜欢混合表/枚举。首先确保此数据是真正静态的。如果有任何变化,您将不得不重新编译和重新部署 如果数据真的是静态的,我会选择枚举路径。您可以创建一个包含所有值的
YearlySalaryEnum
。对于字符串表示,我将使用带有字符串值的字典,并将yearlysalarynum
作为键。字典可以作为静态类中的静态实例保存。用法大致如下(C#):
使用枚举(用于代码)和DB文本(用于GUI演示)
因此,如果您总是有3个选项使用enum
LowSalary
、MiddleSalary
和HighSalary
,请将文本存储在DB中,并在GUI中切换与属性enum值对应的文本。同时使用这两个选项,您应该调查代码域。使用此功能,您可以编写代码生成例程,允许编译过程通过读取数据库自动生成包含这些枚举的程序集或类。这样,您可以让数据库驱动,但不是每次访问枚举实例时都调用数据库 由于C#不允许使用字符串值的枚举,因此我建议使用带有一些静态字符串的结构
通过这种方式,您可以维护一些Intellisense,但不需要尝试在数据库中的字符串值上强加枚举值
我将提供的另一个解决方案是:删除依赖于这些值的逻辑,并转移到基于表的逻辑。(例如,如果每个traunch具有不同的税率,请将税率作为列添加到数据库中,而不是代码中的{}。)。一种方法是编写一个格式化程序,将枚举转换为字符串表示形式:
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));
格式化程序可以通过格式化字符串、多种类型、本地化等扩展以支持不同的格式。看看我的建议 基本上,我对核心查找数据使用默认值sql脚本,对来自其他表的FK引用使用ID,然后使用简单的T4模板生成c#的枚举。这样,数据库就高效、规范化和正确约束,我的c#实体不必处理ID(幻数) 它很简单,快速,简单,为我做的工作
我使用EF4,但您不需要,可以将这种方法用于您的实体使用的任何技术 对于静态项,我为每个元素使用带有[Description()]属性的Enum。 和T4模板,用于重新生成带有生成说明的枚举(或在需要时) 像这样使用它
string str = EnumSalary.Mid.Description()
p.S.还为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.");
}
公共静态TEnum ToDescriptionEnum(此字符串描述)
{
类型enumType=typeof(TEnum);
foreach(Enum.GetNames(enumType)中的字符串名)
{
var enValue=Enum.Parse(enumType,name);
if(Description((Enum)enValue).Equals(Description)){
回报(十纳姆)环境价值;
}
}
抛出新的TargetException(“字符串不是指定枚举的描述或值”);
}
SQL报告的功能如何?如何使用仅枚举的方法解决这个问题。从DB初始化字典,非常简单。如果枚举后面的数据类型是整数,那么将其映射到db列是很简单的。正如Aaron所指出的,许多ORM都可以开箱即用,这就是一个例子,它不会改变。不管怎样,我喜欢您的方法,您将如何在整个应用程序中保持数据。99%的应用程序不需要这些数据,这会不会有任何性能问题?如果很少访问这些数据,您可以将其保存在一个静态类中,该类在您第一次请求数据时初始化(延迟初始化)。只需确保锁已到位,以便一次只有一个线程可以访问该数据。这将消除任何启动减速。如果您不想在第一次访问数据时等待,还可以将数据加载到低优先级工作队列中,以便在数据空闲一两分钟时加载(或在需要之前立即加载)如果它真的不会改变,并且你没有数据库,你可以将它存储在你的app.config文件中的一个自定义部分。真的,我不明白这里的意思。如果文本发生更改,它应该在数据库中,但当您从数据库加载它时,您会将它与枚举相关联。这就是感觉
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.");
}