Перечисления или таблицы?

Я делаю это сообщество 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, сохраните свои тексты в БД и переключите свои тексты в графическом интерфейсе, соответствующем вашему значению перечисления свойства.