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

Tsql 首先在代码中添加新列后删除默认约束,tsql,entity-framework-migrations,Tsql,Entity Framework Migrations,当使用代码优先迁移向表中添加新的不可为null的列时,它将自动为您创建一个默认值。这是有意义的,因为现有行需要为新列指定一个值(因为它不能为null)。那很好,但是在这个值被分配到所有地方之后,我不再需要它了。它不可为null,因为我希望确保始终显式插入值。如果所有内容都默认为“”或0,则我将使用魔术字符串。所以不管怎样,我可以想出一个解决方案,我并不感到兴奋,但它是有效的 添加列后,我将删除默认约束 public override void Up() { AddColumn("dbo.

当使用代码优先迁移向表中添加新的不可为null的列时,它将自动为您创建一个默认值。这是有意义的,因为现有行需要为新列指定一个值(因为它不能为null)。那很好,但是在这个值被分配到所有地方之后,我不再需要它了。它不可为null,因为我希望确保始终显式插入值。如果所有内容都默认为“”或0,则我将使用魔术字符串。所以不管怎样,我可以想出一个解决方案,我并不感到兴奋,但它是有效的

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

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

优点:一旦实现了helper方法,我只需要添加一条简单的线来删除约束。 缺点:似乎没有必要仅仅为了删除而创建索引

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

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));
}
优点:看起来更简单/更干净

缺点:必须临时更改我的约束条件(我假设这在事务中运行,因此我们不应该允许错误数据进入)。大型表上的更新速度可能较慢

哪种方法更可取?还是我错过了更好的方法


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

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

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

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

我可能会考虑稍加修改:我可能会在SQL中创建约束,以避免查找引擎指定的默认名称,例如:

Sql("ALTER TABLE tablename
  ADD columnname type NOT NULL
  CONSTRAINT DF_tablename_columnname DEFAULT defaultvalue");
Sql(“更改表tablename
添加columnname类型不为NULL
约束DF_tablename_columnname默认值”);
(可以重写为使用辅助函数。)

删除约束就如同执行单个ALTER TABLE语句一样简单:

Sql("ALTER TABLE tablename
  DROP CONSTRAINT DF_tablename_columnname");
Sql(“更改表tablename
删除约束DF_tablename_columnname”);
(这里也可以很容易地使用助手函数。)


但这一切都可能是我身上的T-SQL开发人员比C#one更响亮的声音。因此,您最好使用您发布的示例中的代码。

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

删除以下默认列值约束----> ALTER TABLE[dbo].[Attachments]为[DocumentUniqueId]添加默认值('00000000-0000-0000-0000-00000000000000')

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

protected override void Up(MigrationBuilder MigrationBuilder)
{
migrationBuilder.AlterColumn(
名称:“ColumnName”,
模式:“dbo”,
表:“表名”,
类型:“唯一标识符”,
可为空:false,
**defaultValueSql:null**
oldClrType:typeof(Guid),
oldType:“唯一标识符”);
}

我什么地方都没有找到,所以我将其发布以帮助其他人,这对数据库清理很有帮助。

感谢您验证我的想法。我确实考虑过自己创建约束,但我更喜欢使用AdScess,因为它易于阅读和一致,也允许一些其他的限制,如独特的。我决定坚持选择1。谢谢。解决方案1对我很有用。到目前为止我找到的最好的。只想补充一点,您可以明确地指定默认值,而不是依赖EF来提供一个:c.String(nullable:false,defaultValue:n/a),例如。以防您希望以受控方式处理旧数据。
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");
        }