Перечисления или таблицы?
Я делаю это сообщество wiki, так как я был бы признателен за подход людей и не обязательно ответ.
Я в ситуации, когда у меня много полей данных типа поиска, которые не меняются. Примером может служить:
Годовая зарплата
Опция: 0 - 25K
Вариант: 25K - 100K
Опция: 100K +
Я хотел бы, чтобы эти параметры были легко доступны через перечисление, но также хотели бы иметь текстовые значения, доступные в БД, поскольку я буду делать отчетность по текстовым значениям, а не по идентификатору. Кроме того, поскольку они являются статическими, я не хочу делать вызовы в БД.
Я думал о дублировании этого в перечислении и таблице, но хотел бы услышать некоторые альтернативные мысли.
Спасибо
Ответы
Ответ 1
Я думаю, что перечисление - плохая идея. Просто учитывая тип данных, которые вы показываете, он может быть изменен. Лучше иметь таблицу базы данных с полями ID/Min/Max/Description, которые вы загружаете, когда ваше приложение инициализируется.
Ответ 2
Для статических элементов я использую Enum с атрибутом [Description()] для каждого элемента.
И шаблон T4 для регенерации перечисления с описаниями на сборке (или всякий раз, когда вы хотите)
public enum EnumSalary
{
[Description("0 - 25K")] Low,
[Description("25K - 100K")] Mid,
[Description("100K+")] High
}
И используйте его как
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.");
}
Ответ 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));
Форматирование может быть расширено для поддержки различных форматов с помощью форматирования строк, нескольких типов, локализации и т.д.
Ответ 4
Я использую оба. В Linq to SQL и EF вы просто превращаете свойство column в тип перечисления. В других рамках вы обычно можете сопоставить столбцу с атрибутом enum. У вас все еще есть таблица первичных ключей в базе данных, содержащая допустимые перечисления.
Вы также можете сделать это с ограничением CHECK в базе данных, но это имеет тенденцию связывать ваши данные с вашим приложением - кто-то, смотрящий только на базу данных, не обязательно будет знать, что означает каждое значение. Поэтому я предпочитаю гибридную таблицу/перечисление.
Ответ 5
Используйте оба параметра, И вы должны исследовать CodeDOM. используя это, вы можете писать процедуры генерации кода, которые позволяют процессу компиляции автоматически генерировать сборку или класс с этими перечислениями в ней, читая базу данных. Таким образом, вы можете позволить приводу базы данных, но вы не совершаете вызовы в базу данных каждый раз, когда вы обращаетесь к экземпляру перечисления...
Ответ 6
Взгляните на мое предложение здесь Как работать с Enums в Entity Framework?
По сути, я использую стандартные значения sql-скриптов для базовых данных поиска, с идентификатором для ссылок FK из других таблиц, а затем я использую простой шаблон T4 для генерации своих перечислений для С#. Таким образом, база данных эффективна, нормализована и правильно ограничена, а мои объекты С# не должны иметь дело с ID (номерами магов).
Простое, легкое и простое задание для меня.
Я использую EF4, но вам не нужно, можете использовать этот подход с помощью любой технологии, которую вы используете для своих объектов.
Ответ 7
Сначала убедитесь, что эти данные действительно статичны. Если что-то изменится, вам придется перекомпилировать и повторно развернуть.
Если данные действительно статичны, я бы пошел по маршруту перечисления. Вы можете создать YearlySalaryEnum
, удерживая все значения. Для строкового представления я бы использовал словарь со строковыми значениями и YearlySalaryEnum
как ключ. Словарь можно хранить как статический экземпляр в статическом классе. Использование было бы по строкам (С#):
string highSalary = StaticValues.Salaries[YearlySalaryEnum.High];
Ответ 8
Так как С# не разрешает перечисления со строковыми значениями, поэтому я бы предложил структуру с некоторыми статическими строками.
Таким образом, вы поддерживаете некоторый Intellisense, но не пытаетесь обучить значение Enum для того, что является строковым значением в базе данных.
Другое решение, которое я бы предложил: удалить логику, которая зависит от этих значений, и перейти к табличной логике. (Например, если каждый трафик имеет другую ставку налога, добавьте ставку налога как столбец в базе данных, а не код {} в коде.).
Ответ 9
Используйте и перечисление (для кода) и тексты DB - для презентации GUI.
Итак, если вы всегда будете иметь 3 варианта, используйте перечисление LowSalary
, MiddleSalary
и HighSalary
, сохраните свои тексты в БД и переключите свои тексты в графическом интерфейсе, соответствующем вашему значению перечисления свойства.