使用代码优先迁移向表中添加新的不可为空的列时,它将自动为您创建一个默认值。这是有道理的,因为现有的行需要有一个新列的值(因为它不能为空)。没关系,但是在到处分配该值之后,我不再想要它了。它是不可为空的,因为我想确保始终显式插入一个值。如果所有内容都默认为 '' 或 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);
}
优点:一旦实现了辅助方法,我只需要添加一个简单的行来删除约束。缺点:似乎没有必要仅仅为了删除它而创建索引。
另一种方法是更改生成的迁移,因此我们将其添加为可为空,更新所有值,然后使其不可为空。
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));
}
优点:看起来更简单/更干净
缺点:必须暂时更改我的约束(我假设这在事务中运行,因此我们不应该允许错误数据进入)。大桌子上的更新可能很慢。
哪种方法更可取?还是有更好的方法让我想念?
注意:我已经演示了您一次性添加和清理列定义的情况。如果您只是清理以前迁移的默认值,则第二种方法没有帮助。