【问题标题】:Entity Framework Code first making a column non-nullable实体框架代码首先使列不可为空
【发布时间】:2013-09-02 08:46:44
【问题描述】:

我首先在我的项目中使用 EF 代码。我的 DataModel 中有以下代码

[HiddenInput(DisplayValue = false)]        
public DateTime? PasswordDate { get; set; }

为了使这个不可为空,我删除了“?”并从包管理器控制台运行 Add-Migration 命令。生成了以下迁移文件。

  public partial class PasswordDate : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.CertificateInfoes", "PasswordDate", c => c.DateTime(nullable: false));
    }

    public override void Down()
    {
        AlterColumn("dbo.CertificateInfoes", "PasswordDate", c => c.DateTime());
    }
}

但是当我运行 Update-Database 命令时:

Update-Database -SourceMigration 201309020721215_PasswordDate

我收到以下错误:无法将值 NULL 插入列“PasswordDate”,表“”;列不允许空值。更新失败。 声明已终止。

请提出解决方案。

【问题讨论】:

    标签: c# sql entity-framework


    【解决方案1】:

    那是因为您在该列中允许 NULL 值,然后尝试使其不可为空。随后它将尝试将您现有的数据迁移到新的不可为空的列中,这将中断,因为您已经在其中有 NULL 值。

    两种解决方案:

    1) 将其改回可空
    2) 给没有值的项目一个默认值。

    【讨论】:

    • 我无法将其改回可为空的。对于第二个选项,我如何定义默认值?我需要在迁移文件中这样做还是需要在我的数据模型中添加它?
    • @HardikBhatia 然后给你的列一个默认日期值,否则你将不得不单独检查空记录并更新它们。
    • 我已经修改了表并确保我的 PasswordDate 列在数据库中不为空。
    • 更改数据库并向空列添加一些值可以解决问题。我首先尝试了这一点,但似乎其他人在搞乱 DB,并在“PasswordDate”列中插入了一行具有空值的行。
    • 在您的向上迁移中添加Sql(@"UPDATE [dbo].[CertificateInfoes] SET [PasswordDate] = CURRENT_TIMESTAMP WHERE [PasswordDate] IS NULL");,这将为您填充数据。回去应该没有任何问题。
    【解决方案2】:

    如果没有为该列提供默认值,则无法直接将不可为空的列添加到表中包含历史数据的表中。

    我做的是

    1. 将该列添加为可为空。
    2. 提供一个 sql 脚本来填充这个新添加的列。
    3. 更改列以使其不可为空。

    代码示例(带有postgres数据库):

     public override void Up()
        {            
            AddColumn("public.YourTableName", "YourColumnName", c => c.Int(nullable: true));
            Sql(@"UPDATE ""public"".""YourTableName""
                  SET ""YourColumnName"" = Value you want to set
                ");
    
            AlterColumn("public.YourTableName", "YourColumnName", c => c.Int(nullable: false));
        }
    

    【讨论】:

      【解决方案3】:

      EF 核心 6 中的另一种方法是更改​​迁移脚本,其中添加列指定默认值。然后您可以稍后再次删除此默认值。

      public partial class AddOrderSource : Migration
      {
          protected override void Up(MigrationBuilder migrationBuilder)
          {
              // Add the column with a default value, then drop the default value.
              // This creates a non-nullable column without the migration failing because of existing data.
      
              migrationBuilder.AddColumn<int>(
                  name: "OrderSource",
                  table: "Orders",
                  type: "int",
                  nullable: false,
                  defaultValue: 1); // Sample default value
      
              migrationBuilder.AlterColumn<int>(
                  name: "OrderSource", 
                  table: "Orders",
                  oldDefaultValue: 1,
                  defaultValue: null
              );
          }
      
          protected override void Down(MigrationBuilder migrationBuilder)
          {
              migrationBuilder.DropColumn(
                  name: "OrderSource",
                  table: "Orders");
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-29
        • 2011-08-23
        • 1970-01-01
        • 1970-01-01
        • 2014-10-24
        • 1970-01-01
        相关资源
        最近更新 更多