我试图使用CF构建一个模型现有数据库。 我有一个专栏,我忘了把一个健全的默认值。 而不是通过改变它危及初始迁移的纯度,我只是想我会创建另一个迁移(这就是迁移是吧?:)
public override void Up()
{
AlterColumn("Config", "DefaultTaxPerDollar", c => c.Decimal(nullable: false, precision: 19, scale: 5, defaultValue: 0.087m));
}
public override void Down()
{
AlterColumn("Config", "DefaultTaxPerDollar", c => c.Decimal(nullable: false, precision: 19, scale: 5, defaultValue: 0.0m));
}
但是,这会产生Column already has a DEFAULT bound to it.
错误从SQL Server。
怎样才能改变使用CF迁移的默认值? 或者说,一个人如何简单地删除默认值(并随后用不同的值重新创建它)?
编辑:
下面是生成的SQL:
ALTER TABLE [Config] ADD CONSTRAINT DF_DefaultTaxPerDollar DEFAULT 0.087 FOR [DefaultTaxPerDollar]
ALTER TABLE [Config] ALTER COLUMN [DefaultTaxPerDollar] [decimal](19, 5) NOT NULL
我想我可能已经找到了解决方案,使用Sql()
方法与启发一些复杂的SQL 这个职位。 问题发生在SQL Server使用约束来实现默认的事实(OH!我是多么的MySQL!)与约束生成的名称茎。 因此,代码一线队不能简单地更改或删除/轻松地重新创建默认值。
缺省约束去除由实体框架的SQL Server产生逆反迁移的启发
public static void DropDefaultConstraint(string tableName, string columnName, Action<string> executeSQL)
{
string constraintVariableName = string.Format("@constraint_{0}", Guid.NewGuid().ToString("N"));
string sql = string.Format(@"
DECLARE {0} nvarchar(128)
SELECT {0} = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'{1}')
AND col_name(parent_object_id, parent_column_id) = '{2}';
IF {0} IS NOT NULL
EXECUTE('ALTER TABLE {1} DROP CONSTRAINT ' + {0})",
constraintVariableName,
tableName,
columnName);
executeSQL(sql);
}
这是略短,但使用的是相同的。
DropDefaultConstraint(TableName, "DefaultTaxPerDollar", q => Sql(q));
GUID是用来做的情况下,你会在一个迁移砸几个约束的唯一变量名。
这里有被激发的解决方案这篇文章 。 这不正是一个优雅的方法,但它为我工作。
public static void DropDefaultConstraint(string tableName, string columnName, Action executeSQL)
{
// Execute query that drops the UDF that finds the default constraint name
var query = @"
-- recreate UDF
if object_id('[dbo].[GetDefaultConstraintName]') is not null
begin
drop function [dbo].[GetDefaultConstraintName]
end
";
executeSQL(query);
// Execute query that (re)creates UDF that finds the default constraint name
query = @"
create function [dbo].[GetDefaultConstraintName] (
@TableName varchar(max),
@ColumnName varchar(max))
returns varchar(max)
as
begin
-- Returns the name of the default constraint for a column
declare @Command varchar(max)
select
@Command = d.name
from
((
sys.tables t join
sys.default_constraints d
on
d.parent_object_id = t.object_id) join
sys.columns c
on
c.object_id = t.object_id and
c.column_id = d.parent_column_id)
where
t.name = @TableName and
c.name = @ColumnName
return @Command
end
";
executeSQL(query);
// Execute query that actually drops the constraint
query = string.Format(@"
-- Use UDF to find constraint name
DECLARE @Constraint_Name VARCHAR(100)
SET @Constraint_Name = [dbo].GetDefaultConstraintName('{0}','{1}')
if LEN(@Constraint_Name) > 0
BEGIN
DECLARE @query VARCHAR(300)
SET @query = 'ALTER TABLE {0} DROP CONSTRAINT ' + @Constraint_Name
execute(@query)
END", tableName, columnName);
executeSQL(query);
}
而在你的迁移,你可以这样调用:
DropDefaultConstraint(TableName, "DefaultTaxPerDollar", q => Sql(q));
之所以使用的兰巴是因为你必须做出三个不同的调用Sql()
我从来没有能够得到这个作为一个长的查询工作-试图关键字的多种组合GO
在许多不同的地方。 我也试图扭转第一查询,这样,如果它不存在的UDF只得到重新的逻辑,并没有奏效。 我想每一次重建是更强大的反正。