【问题标题】:Nullable enum field with Code First Approach doesn't create the enum Field in Database使用代码优先方法的可空枚举字段不会在数据库中创建枚举字段
【发布时间】:2013-11-25 16:47:51
【问题描述】:

我使用代码优先的方法来创建架构,然后在 Seed 方法的帮助下填充其中的数据

我正在使用实体框架版本 5.0、SQLEXPRESS2008 和 MVC4

下面是我的模型

  public enum Grade
{
    A, B, C, D, F
}

public class Enrollment
{
    public int EnrollmentID { get; set; }
    public int CourseID { get; set; }
    public int StudentID { get; set; }
    [DisplayFormat(NullDisplayText = "No grade")]
    public Grade? Grade { get; set; }
    public virtual Course Course { get; set; }
    public virtual Student Student { get; set; }
}

这就是我在 Intializer 中使用种子方法将数据填充到数据库的方式

 var enrollments = new List<Enrollment>
        {
        new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
        new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
        new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
        new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
        new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
        new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
        new Enrollment{StudentID=3,CourseID=1050},
        new Enrollment{StudentID=4,CourseID=1050,},
        new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
        new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
        new Enrollment{StudentID=6,CourseID=1045},
        new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
        };
        enrollments.ForEach(s => context.Enrollments.Add(s));
        context.SaveChanges();

在调试时,我可以在该上下文中看到“等级”列中的数据

但它既不会在数据库中创建“等级”列,也不会填充其数据。

我在 web.config 中设置了 Context 和 Database Initalizer,如下所示

   <entityFramework>
  <context type="EntityFrameworkWithMVC.DAL.SchoolContext, EntityFrameworkWithMVC">
    <databaseInitializer type="EntityFrameworkWithMVC.DAL.SchoolInitializer,  EntityFrameworkWithMVC" />
    </context>
   </contexts>
  </entityFramework>

【问题讨论】:

  • 是的,我在 web.config 中设置了它。Schema 是在 DB 中创建的。但只有这个字段没有被创建。
  • 请查看修改后的帖子。你想让我放整个 Intializer 类吗?
  • 对不起,我的错:只是缺少Grade 列吗?您是否在初始数据库创建后添加它?如果是这样的话;尝试通过手动删除来重新创建数据库。如果创建了Grade 字段,那一定是你的迁移策略。最后一件事:您使用的是 .NET 4.5 吗? EF5 中的 enum 功能需要它
  • 我已经重复了 4-5 次重新创建数据库的过程。但它没有帮助。仅供参考。它的可空类型。我正在使用 .NET 框架版本 4.0。是的,它也在 Asp.net 网站上的 Contoso 大学示例中给出。

标签: c# entity-framework asp.net-mvc-4 ef-code-first


【解决方案1】:

您将需要 .NET 4.5

在带有 .NET 4.0 的 EF 5 中不提供枚举支持。这是因为 System.Data.Entity 发生了变化,它不在 EF 5 库中,而是在 .NET 4.5 版本中。

见: http://social.msdn.microsoft.com/Forums/en-US/55dc58a4-6190-4bad-b317-1787cf86bf3d/ef-5-but-no-enum-support?forum=adodotnetentityframework

Are there technical reasons EF 5 isn't fully supported on .NET4.0?

您需要一种解决方法来提取您的 enum 值(您可以使用 int 并在映射中转换为 enum)或升级到 .NET 4.5

[更新] 至于解决方法,有几个选项, 在所有情况下,您都需要将 enum 值作为 string 或 int(或其他支持的类型)写入数据库:

  • 使用映射器

如果您使用 ViewModel 或类似的东西,您可以实现一个可配置的映射器,如 AutoFac (http://www.nuget.org/packages/Autofac/)。一开始使用起来有点困难,但它具有 IOC、MVC 等的所有功能。您可以定义自定义映射定义,以便可以在 ViewModel 中使用 enum 并在实体中使用 int 值。自定义映射包含从int 到enum 以及返回的转换。

  • 使用 [NotMapped] 列

这实现起来更快,但它通常会咬你的尾巴:

public int? GradeValue {get;set;}

[NotMapped]
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade 
{ 
    get 
    { 
         return GradeValue.HasValue ? (Grade?) GradeValue.Value : null; 
    } 
}

[NotMapped] 属性确保enum 不会添加到数据库中(如果您稍后决定升级到 .NET 4.5,可能会派上用场)。

现在您可以将值读取为enum。我的猜测是GradeValue 需要公开(私有/受保护会给您带来一些优势)(不确定此版本是否支持)。如果必须是public;这有点棘手,因为其他开发人员可能会直接使用这个GradeValue。

或者,您可以对set 指令执行类似的操作。

希望这会有所帮助。

【讨论】:

  • @HarshilGandhi:有,但这取决于您的代码/项目。我会更新帖子。
  • 感谢 stefan 的帮助。在为每个枚举值分配整数值后,我将其转换为 int。现在可以使用。
猜你喜欢
  • 2012-11-14
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-21
相关资源
最近更新 更多