Подтвердить что ты не робот

Лучший способ хранения Enum в базе данных

Каков наилучший способ хранения Enum в базе данных с использованием С# и Visual Studio и MySQL Data Connector.

Я собираюсь создать новый проект с более чем 100 Enums, и большинство из них нужно будет сохранить в базе данных. Создание конвертеров для каждого из них будет длительным процессом, поэтому мне интересно, есть ли у visual studio или кто-то есть какие-то методы для этого, о которых я не слышал.

4b9b3361

Ответ 1

    [Required]
    public virtual int PhoneTypeId
    {
        get
        {
            return (int)this.PhoneType;
        }
        set
        {
            PhoneType = (PhoneTypes)value;
        }
    }
    [EnumDataType(typeof(PhoneTypes))]
    public PhoneTypes PhoneType { get; set; }

public enum PhoneTypes
{
    Mobile = 0,
    Home = 1,
    Work = 2,
    Fax = 3,
    Other = 4
}

Работает как шарм! Нет необходимости конвертировать (int) Enum или (Enum) int в код. Просто используйте enum и ef-код, сначала сохраните int для вас. p.s.: "[EnumDataType (typeof (PhoneTypes))]" атрибут не требуется, просто дополнительный, если вы хотите получить дополнительную функциональность.

В качестве альтернативы вы можете:

[Required]
    public virtual int PhoneTypeId { get; set; }
    [EnumDataType(typeof(PhoneTypes))]
    public PhoneTypes PhoneType
    {
        get
        {
            return (PhoneTypes)this.PhoneTypeId;
        }
        set
        {
            this.PhoneTypeId = (int)value;
        }
    }

Ответ 2

Мы храним наши как ints или longs, а затем можем просто бросить их туда и обратно. Вероятно, это не самое надежное решение, но это то, что мы делаем.

мы используем типизированные DataSets, поэтому, например:

eunum BlockTreatmentType 
{
    All = 0
};

// blockTreatmentType is an int property
blockRow.blockTreatmentType = (int)BlockTreatmentType.All;
BlockTreatmentType btt = (BlockTreatmentType)blockRow.blocktreatmenttype;

Ответ 3

В конце концов вам понадобится отличный способ справиться с повторяющимися задачами кодирования, такими как конвертеры enum. Вы можете использовать генератор кода, например MyGeneration или CodeSmith среди многих других или, возможно, ORM mapper, например nHibernate, чтобы обрабатывать все для вас.

Что касается структуры... с сотнями перечислений, я бы сначала подумал о том, чтобы попытаться организовать данные в одну таблицу, которая может выглядеть примерно так: (псевдо sql)

MyEnumTable(
EnumType as int,
EnumId as int PK,
EnumValue as int )

который позволит вам хранить информацию об enum в одной таблице. EnumType также может быть внешним ключом к таблице, которая определяет различные перечисления.

Ваши объекты biz будут связаны с этой таблицей через EnumId. Тип перечисления существует только для организации и фильтрации в пользовательском интерфейсе. Использование всего этого, конечно, зависит от структуры кода и проблемной области.

Btw, в этом сценарии вы хотели бы установить кластерный индекс в EnumType, а не оставлять idx кластера по умолчанию, который создается на PKey.

Ответ 4

Некоторые вещи, которые вы должны принять во внимание.

Будет ли столбец перечисления использоваться напрямую другими приложениями, например, для отчетов. Это ограничит возможность хранения перечисления в нем целочисленным форматом, поскольку это значение не будет иметь смысла, если оно присутствует в отчете, если отчеты не имеют пользовательской логики.

Каковы потребности i18n в вашем приложении? Если он поддерживает только один язык, вы можете сохранить перечисление как текст и создать вспомогательный метод для преобразования из строки описания. Вы можете использовать [DescriptionAttribute] для этого, и методы для преобразования, вероятно, можно найти, выполнив поиск SO.

Если, с другой стороны, вам необходимо поддерживать множественный доступ к языку и внешнему приложению к вашим данным, вы можете начать рассматривать, действительно ли перечисление является ответом. Другие варианты, такие как таблицы поиска, могут быть рассмотрены, если сценарий более сложный.

Перечисления превосходны, когда они содержатся в коде... когда они пересекают эту границу, вещи, как правило, немного запутаны.


Update:

Вы можете преобразовать из целого числа с помощью метода Enum.ToObject. Это означает, что вы знаете тип перечисления при преобразовании. Если вы хотите сделать это полностью универсальным, вам нужно сохранить тип перечисления вместе с ним в базе данных. Вы можете создать таблицы поддержки словаря данных, чтобы указать, какие столбцы являются перечислениями и какой тип они являются.

Ответ 5

Если вы хотите сохранить все ваши значения перечислений, вы можете попробовать следующие таблицы для хранения перечислений и их членов и фрагмента кода для добавления этих значений. Я бы сделал это только во время установки, поскольку эти значения никогда не изменятся, пока вы не перекомпилируете!

Таблица DB:

   create table EnumStore (
    EnumKey int NOT NULL identity primary key,
    EnumName varchar(100)
);
GO

create table EnumMember (
    EnumMemberKey int NOT NULL identity primary key,
    EnumKey int NOT NULL,
    EnumMemberValue int,
    EnumMemberName varchar(100)
);
GO
--add code to create foreign key between tables, and index on EnumName, EnumMemberValue, and EnumMemberName

С# фрагмент:

void StoreEnum<T>() where T: Enum
    {
        Type enumToStore = typeof(T);
        string enumName = enumToStore.Name;

        int enumKey = DataAccessLayer.CreateEnum(enumName);
        foreach (int enumMemberValue in Enum.GetValues(enumToStore))
        {
            string enumMemberName = Enum.GetName(enumToStore, enumMemberValue);
            DataAccessLayer.AddEnumMember(enumKey, enumMemberValue, enumMemberName);
        }
    }

Ответ 6

Если вам нужно сохранить в строковых значениях DB поля enum, лучше, как показано ниже. Например, это может потребоваться, если вы используете SQLite, которые не поддерживают поля enum.

[Required]
public string PhoneTypeAsString
{
    get
    {
        return this.PhoneType.ToString();
    }
    set
    {
        PhoneType = (PhoneTypes)Enum.Parse( typeof(PhoneTypes), value, true);
    }
}

public PhoneTypes PhoneType{get; set;};

public enum PhoneTypes
{
    Mobile = 0,
    Home = 1,
    Work = 2,
    Fax = 3,
    Other = 4
}

Ответ 7

Я не уверен, является ли он наиболее гибким, но вы можете просто сохранить его строковые версии. Это, конечно, читаемо, но, возможно, сложно поддерживать. Enums конвертировать из строк и обратно довольно легко:

public enum TestEnum
{
    MyFirstEnum,
    MySecondEnum
}

static void TestEnums()
{
    string str = TestEnum.MyFirstEnum.ToString();
    Console.WriteLine( "Enum = {0}", str );
    TestEnum e = (TestEnum)Enum.Parse( typeof( TestEnum ), "MySecondEnum", true );
    Console.WriteLine( "Enum = {0}", e );
}

Ответ 8

Почему бы не попытаться полностью отделить перечисления от БД? Я нашел эту статью отличной ссылкой, работая над чем-то подобным:

http://stevesmithblog.com/blog/reducing-sql-lookup-tables-and-function-properties-in-nhibernate/

Идеи в ней должны применяться независимо от того, какую БД вы используете. Например, в MySQL вы можете использовать тип данных "enum" для обеспечения соответствия вашим закодированным перечислениям:

http://dev.mysql.com/doc/refman/5.0/en/enum.html

Приветствия