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

Enum как ключ в структуре сущности 5 ошибка бросания на многих-многих объединениях

ОК, это немного длинный/неясный, но я получаю странную ошибку в конкретной ситуации, когда я использую Enum в качестве ключевого слова таблицы и пытаюсь выполнить запрос к таблице, в то время как в нее входит более одного многого связанных с ними.

Ошибка, приведенная в следующем примере:

The type of the key field 'DietIs' is expected to be 'MvcApplication8.Models.DietIs', but the value provided is actually of type 'System.Int32'.

В веб-проекте .net 4.5 у меня есть следующая конфигурация сущности:

public enum DietIs {
    None,
    Kosher,
    Paleo,
    Vegetarian
}

public class Diet {

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public DietIs DietIs { get; set; }

    public string Description { get; set; }
    public virtual ICollection<Recipe> Recipes { get; set; }
    public virtual ICollection<Menu> Menus { get; set; }
}

public class Recipe {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Diet> Diets { get; set; }
}

public class Menu {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Diet> Diets { get; set; }
}

public class EnumTestContextInit : DropCreateDatabaseAlways<EnumTestContext> {}

public class EnumTestContext : DbContext {
    public DbSet<Diet> Diets { get; set; }
    public DbSet<Menu> Menus { get; set; }
    public DbSet<Recipe> Recipes { get; set; }

    public EnumTestContext() : base("EnumTestContext") {
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }
}

В файле Global.asax.cs я инициализирую базу данных:

 Database.SetInitializer(new EnumTestContextInit());
        using (var context = new EnumTestContext()) {

            var noDiet = new Diet { DietIs = DietIs.None, Description = "Whatever you want" };
            var paleoDiet = new Diet { DietIs = DietIs.Paleo, Description = "Like paleolithic peoples" };
            var vegDiet = new Diet { DietIs = DietIs.Vegetarian, Description = "No meat" };

            context.Menus.Add(new Menu { Name = "Cheese burger with Fries Menu", Diets = new List<Diet> { noDiet } });
            context.Menus.Add(new Menu { Name = "Mammoth Steak Tartar with Nuts Menu", Diets = new List<Diet> { paleoDiet, noDiet } });
            context.Menus.Add(new Menu { Name = "Soy Cheese Pizza Menu", Diets = new List<Diet> { vegDiet, noDiet } });

            context.Recipes.Add(new Recipe {Name = "Cheese burger", Diets = new List<Diet> {noDiet}});
            context.Recipes.Add(new Recipe { Name = "Mammoth Steak Tartar", Diets = new List<Diet> { paleoDiet, noDiet} });
            context.Recipes.Add(new Recipe { Name = "Cheese Pizza", Diets = new List<Diet> { vegDiet, noDiet } });

            context.SaveChanges();
        }

Затем я пытаюсь выполнить запрос к базе данных:

var context = new EnumTestContext();

        var dietsWithMenusAndRecipes = context.Diets
                  .Include(e => e.Menus)
                  .Include(e => e.Recipes)
                  .ToList();

Другие запросы, в которых я использую один, включают загрузку ожидаемых данных без проблем. Вышеуказанный запрос с двумя вариантами включает ошибку выше. В базе данных я вижу таблицы автогенерированных соединений (MenuDiets и RecipeDiets), и все данные выглядят правильно. Опять же, как и в приведенных выше примерах, я могу запросить данные, но не могу включить несколько связанных объектов, не выкидывая ошибку.

Если я изменил последний запрос, чтобы использовать только один include, я могу загрузить другую таблицу без проблем:

        var dietsWithMenusAndRecipes = context.Diets
                 .Include(e => e.Menus).ToList();

        foreach (var item in dietsWithMenusAndRecipes) {
            context.Entry(item).Collection(e => e.Recipes).Load();
            var rec = item.Recipes;
        }

Далее - хотя это не удовлетворяет моему варианту использования, так как я хочу ограничить таблицу только значениями перечисления, а уникальные ограничения не поддерживаются в EF - это будет работать, если я изменю класс сущности Diet, чтобы использовать отдельный идентификатор ключ, а не ключ Enum:

    public int Id { get; set; }
    public DietIs DietIs { get; set; }

Еще одно возможное решение, которое я изучил, заключалось в том, чтобы явно создавать таблицы соединений (MenuDiets и RecipeDiets), чтобы ключ свойства соединения был введен как Enum, но это все еще возвращало вышеуказанную ошибку.

Кажется, что это несколько включений, которые заставляют его задыхаться. Любые идеи относительно того, что я делаю что-то неправильно в настройке модели? Сам запрос? Ошибка в Entity Framework?

4b9b3361

Ответ 1

Проблема заключается в том, что enum в .NET является типом класса. Из определения на этой странице:

Предоставляет базовый класс для перечислений.

И это замечание:

Перечисление представляет собой набор именованных констант, базовый тип которых любой интегральный тип. Если базовый тип явно не объявлен, Int32 используется. Enum является базовым классом для всех перечислений в .NET. Framework.

Да, он определяет набор констант, тип которых является интегральным типом, но когда вы объявляете ключ yor:

public DietIs DietIs { get; set; }

Ваш ключ - это тип класса, не являющийся интегральным типом; вам может потребоваться выполнить его при сравнении или присвоении значений целочисленного типа. На этом примере приведен пример конверсий:

Вы можете конвертировать между элементом перечисления и его базовым типом с помощью операции литья (в С#) или преобразования (в Visual Basic). В следующем примере используются операторы обсадной колонны или преобразования для выполнения конверсии как из целого числа в значение перечисления, так и из значение перечисления в целое число.

public enum ArrivalStatus { Late=-1, OnTime=0, Early=1 };


int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus) value3;
int value4 = (int) status3;