.net - 枚举作为 Entity Framework 5 中的键在多对多连接上抛出错误

标签 .net entity-framework enums .net-4.5 entity-framework-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 web 项目中,我有以下实体配置:
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)并且所有数据看起来都是正确的。同样,在上面的示例中,我可以查询数据,但不能在不抛出错误的情况下包含多个相关实体。

如果我将最后一个查询更改为仅使用一个包含,我可以毫无问题地加载另一个表:
        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 实体类更改为使用单独的身份键,这将起作用,而不是比枚举键:
    public int Id { get; set; }
    public DietIs DietIs { get; set; }

我探索的另一个可能的解决方案是显式创建连接表(MenuDiets 和 RecipeDiets),以便将连接属性键输入为 Enum,但这仍然返回上述错误。

它似乎真的是导致它窒息的多个包含。关于我是否在模型设置中做错了什么有什么想法吗?查询本身? Entity Framework 中的错误?

最佳答案

问题似乎在于 enum在.NET 中是一个类类型。来自 this page 上的定义:

Provides the base class for enumerations.



还有这句话:

An enumeration is a set of named constants whose underlying type is any integral type. If no underlying type is explicitly declared, Int32 is used. Enum is the base class for all enumerations in the .NET Framework.



是的,它定义了一组常量,其类型是整数类型,但是当您声明 yor 键时:
public DietIs DietIs { get; set; }

你的键实际上是一个类类型而不是一个整数类型;在比较或分配整数类型的值时,您可能必须强制转换它。该页面提供了有关转换的示例:

You can convert between an enumeration member and its underlying type by using a casting (in C#) or conversion (in Visual Basic) operator. The following example uses casing or conversion operators to perform conversions both from an integer to an enumeration value and from an enumeration value to an integer.


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


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

关于.net - 枚举作为 Entity Framework 5 中的键在多对多连接上抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12220956/

相关文章:

PostgreSQL:更改枚举类型的列

Java 枚举泛型

c# - 犀牛模拟 : Mocking private method calls c#

c# - 将 AvalonEdit 绑定(bind)到 XML

c# - 如何在我的具体情况下实现 IEnumerable?

c# - EF 上下文中基于动态角色的身份验证过滤器

c++ - 使用枚举类作为模板参数缩短模板函数调用

c# - 从 C# 中的字符串中删除最后一个字符。一种优雅的方式?

c# - 在 IIS 7.5 上对 WebApi 服务的 HttpClient 调用 - 404 未找到

c# - 层和实体?