首先在代码中添加新列后删除默认约束

时间:2012-06-03 09:00:58

标签: tsql ef-migrations

使用代码优先迁移向表中添加新的非可空列时,它会自动为您创建默认值。这是有道理的,因为现有行需要具有新列的值(因为它不能为空)。那很好,但是在那个价值分配到处之后,我再也不想要了。它是不可空的,因为我想确保始终显式插入一个值。如果一切都默认为''或者0然后我会有魔法字符串。所以无论如何,我可以提出一个解决方案,我并不感到兴奋,但它确实有效。

添加列后,我删除默认约束。

public override void Up()
{
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false));
    Sql(Helpers.DropDefaultConstraint("dbo.SomeTable", "NewColumn"));
}

...

public static string DropDefaultConstraint(string table, string column)
{
    return string.Format(@"
        DECLARE @name sysname

        SELECT @name = dc.name
        FROM sys.columns c
        JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id
        WHERE c.object_id = OBJECT_ID('{0}')
        AND c.name = '{1}'

        IF @name IS NOT NULL
            EXECUTE ('ALTER TABLE {0} DROP CONSTRAINT ' + @name)
        ",
        table, column);
}

PROS:一旦实现了辅助方法,我只需要添加一条简单的行来删除约束。 缺点:似乎没有必要创建一个索引只是为了删除它。

另一种方法是更改​​生成的迁移,因此我们添加它可以为空,更新所有值,然后使其不可为空。

public override void Up()
{
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int());
    Sql("UPDATE dbo.SomeTableSET NewColumn= 1");
    AlterColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false));
}

PROS:似乎更简单/更清洁

缺点:必须暂时改变我的约束(我假设它在一个事务中运行,因此我们不应该允许坏数据)。大表的更新可能会很慢。

哪种方法更可取?还是有更好的方法让我失踪?

注意:我已经演示了一次添加和清除列定义的情况。如果您只是清理以前迁移的默认值,第二种方法没有帮助。

2 个答案:

答案 0 :(得分:11)

我个人认为第一种方法没有错。是的,您必须创建默认约束以将非可空列添加到非空数据集。是的,如果您需要确保将来根据您的要求明确添加新列,则必须在之后删除它。

即使你仍然遇到这种方法的问题,问题是,除了你的第二种方法之外,很可能没有其他选择。使用默认值更新可能较大的表的成本似乎比创建和立即删除默认约束的成本更高。

我可能会考虑稍作修改:我可能会在SQL中创建约束,以避免查找引擎分配的默认名称这样的大惊小怪,如下所示:

Sql("ALTER TABLE tablename
  ADD columnname type NOT NULL
  CONSTRAINT DF_tablename_columnname DEFAULT defaultvalue");

(可以重写以使用辅助函数。)

删除约束将与执行单个ALTER TABLE语句一样简单:

Sql("ALTER TABLE tablename
  DROP CONSTRAINT DF_tablename_columnname");

(同样,这里可以很容易地使用辅助函数。)

但是我说T-SQL开发人员可能比C#更响亮。所以你很可能会像你发布的例子那样使用代码。

答案 1 :(得分:0)

首先使用EF代码从列中删除默认值约束的解决方案-如果列不再具有NULL值[Not Null],则可以使用下面的Code First方法从表中删除下面的SQL脚本。在迁移文件中设置“ defaultValueSql:null”。

删除以下默认列值约束----> ALTER TABLE [dbo]。[附件]为[DocumentUniqueId]添加默认('00000000-0000-0000-0000-000000000000')

首先应用此代码C#---->

protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AlterColumn<Guid>(
                name: "ColumnName",
                schema: "dbo",
                table: "TableName",
                type: "uniqueidentifier",
                nullable: false,
                **defaultValueSql: null,**
                oldClrType: typeof(Guid),
                oldType: "uniqueidentifier");
        }

我一无所获,所以我将其发布以帮助其他人,这对数据库清理很有帮助。