Gen*_*ick 25 .net enums entity-framework .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'.
Run Code Online (Sandbox Code Playgroud)
在.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;
}
}
Run Code Online (Sandbox Code Playgroud)
在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();
}
Run Code Online (Sandbox Code Playgroud)
然后,我尝试查询数据库:
var context = new EnumTestContext();
var dietsWithMenusAndRecipes = context.Diets
.Include(e => e.Menus)
.Include(e => e.Recipes)
.ToList();
Run Code Online (Sandbox Code Playgroud)
我使用单个的其他查询包括加载预期数据而没有问题.上面的查询,包括两个包括抛出上面的错误.在数据库中,我看到自动生成的连接表(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;
}
Run Code Online (Sandbox Code Playgroud)
进一步 - 虽然这不满足我的用例,因为我想将表限制为枚举值,并且EF中不支持唯一约束 - 如果我将Diet实体类更改为使用单独的身份密钥,这将起作用比Enum键:
public int Id { get; set; }
public DietIs DietIs { get; set; }
Run Code Online (Sandbox Code Playgroud)
另一种可能的解决方案我探索是明确创建的连接表(MenuDiets和RecipeDiets),使联接属性密钥类型为枚举,但仍返回上面的错误.
它似乎真的是导致它窒息的多个包含.关于我是否在模型设置中做错了的任何想法?查询本身?实体框架中的错误?
问题似乎是enum在.NET中是类类型的事实.从此页面上的定义:
提供枚举的基类.
这句话:
枚举是一组命名常量,其基础类型是任何整数类型.如果未显式声明基础类型,则使用Int32.Enum是.NET Framework中所有枚举的基类.
是的,它定义了一组常量,其类型是一个整数类型,但是当你声明yor键时:
public DietIs DietIs { get; set; }
Run Code Online (Sandbox Code Playgroud)
你的密钥实际上是一个类型而不是整数类型; 在比较或分配整数类型的值时,您可能必须将其强制转换.该页面提供了有关转化的示例:
您可以使用转换(在C#中)或转换(在Visual Basic中)运算符在枚举成员及其基础类型之间进行转换.以下示例使用套接字或转换运算符执行从整数到枚举值以及从枚举值到整数的转换.
public enum ArrivalStatus { Late=-1, OnTime=0, Early=1 };
int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus) value3;
int value4 = (int) status3;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2517 次 |
| 最近记录: |