使用代码优先迁移将新的非空列添加到表中时,它将自动为您创建一个默认值。这是有道理的,因为现有行需要为新列具有一个值(因为它不能为null)。很好,但是在将该值分配到所有位置之后,我不再想要它了。它是不可为空的,因为我想确保始终显式插入一个值。如果所有内容都默认为''或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:似乎更简单/更干净
CONS:必须临时更改约束(我假设此约束在事务中运行,因此我们不应该允许输入不良数据)。在大表上更新可能会很慢。
哪种方法更可取?还是我想念一种更好的方法?
注:我已经演示了一次性添加和清除列定义的情况。如果您只是清理以前的迁移中的默认值,则第二种方法没有帮助。
不过,我可能会考虑进行一些修改:我可能会在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#。因此,您很可能会使用与所发布示例类似的代码。
首先应用此代码C#---->
受保护的覆盖无效Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterColumn( 名称:“ ColumnName”, 模式:“ dbo”, 表格:“ TableName”, 类型:“ uniqueidentifier”, 可为空:false,
defaultValueSql:空,
oldClrType:typeof(Guid), oldType:“ uniqueidentifier”); }我一无所获,所以我将其发布以帮助其他人,这对数据库清理很有帮助。
-vaya