枚举作为实体框架的关键5在多对多连接中抛出错误 [英] Enum as Key in entity framework 5 throwing error on many to many joins

查看:100
本文介绍了枚举作为实体框架的关键5在多对多连接中抛出错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这有点冗长/晦涩,但是在特定情况下,我会使用枚举作为表格键,并尝试查询表,同时包含多个多对多相关实体。

OK, this is a bit lengthy / obscure, but I'm getting an odd error in specific situation where I use an Enum as a table Key and attempt to query against the table while including more than one many-to-many related entities.

以下示例代码中的错误是:

The error, from the example code below is:

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项目中,我有以下实体配置:

In a .net 4.5 web project, I have the following entity configuration :

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文件中,我初始化数据库:

In the Global.asax.cs file I initialize the database:

 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();
        }

然后,我尝试针对数据库进行查询:

Then, I attempt to query against the database:

var context = new EnumTestContext();

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

我使用单个的其他查询包括加载预期的数据而没有问题。上面的查询,有两个包括抛出上面的错误。在数据库中,我看到自动生成的连接表(MenuDiets和RecipeDiets),所有数据看起来都正确。再次,如上面的例子,我可以查询数据,但不能包含多个相关的实体,而不会抛出错误。

Other queries where I use a single include load the expected data without issue. The query above, with two includes throws the error above. In the database I see autogenerated join tables (MenuDiets and RecipeDiets) and all the data looks correct. Again, as in the examples above I can query against the data but can't include multiple related entities without throwing the error.

如果我将最后一个查询更改为仅使用单个包含,我可以加载另一个表,而不会出现问题:

If I change the last query to only use a single include, I can load the other table without issue:

        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键,这将会起作用:

Further — though this does not satisfy my use case as I want to restrict the table to just the enum values and unique constraints aren't supported in EF — this will work if I change the Diet entity class to use a separate identity key, rather than the Enum key:

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

我探讨的另一个可能的解决方案是明确创建连接表(MenuDiets和RecipeDiets),以便join属性键被输入为枚举,但是这仍然返回上面的错误。

Another possible solution I explored was to explicitly create the join tables (MenuDiets and RecipeDiets) so that the join property key was typed as the Enum, but this still returned the above error.

它似乎是多个包含导致它窒息的包含。关于我在模型设置中是否出现错误的任何想法?查询本身?实体框架中的错误?

It really seems to be the multiple Includes that are causing it to choke. Any ideas as to whether I'm doing something wrong in the model setup? The query itself? A bug in Entity Framework?

推荐答案

这个问题似乎是枚举是类类型。从此页面

The issue seems to be the fact that enum in .NET is a class type. From the definition on this page:


为枚举提供基类。

Provides the base class for enumerations.

这句话:


枚举是一组命名常量其底层类型是
任何整数类型。如果没有明确声明底层类型,则使用Int32
。枚举是.NET
框架中所有枚举的基类。

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键:

Yes it defines a set of constants whose type is an integral type but when you declare yor key:

public DietIs DietIs { get; set; }

您的密钥实际上是一个类型不是整数类型;当比较或分配积分类型的值时,您可能需要投掷它。该页面提供了有关转换的示例:

Your key is actually a class type not an integral type; you may have to cast it when comparing or assigning values of integral type. The page provides this example about conversions:


您可以通过使用转换在枚举成员和基础类型
之间进行转换在C#)或转换(在Visual Basic中)运算符。
以下示例使用套接字或转换运算符执行从整数到枚举值和
枚举值到整数的
转换。

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;

这篇关于枚举作为实体框架的关键5在多对多连接中抛出错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆