I'm trying to use CF to build a model for an existing database. I have a column in which I forgot to set a sane default value. And rather than compromise the purity of the initial migration by changing it, I just figured I'd create another migration (that's what migrations are for, right? :)
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));
}
But this produces Column already has a DEFAULT bound to it.
error from the SQL Server.
How does one change a default value using CF migrations? Or, how does one simply remove a default value (and subsequently re-create it with a different value)?
Edit:
Here is the SQL generated:
ALTER TABLE [Config] ADD CONSTRAINT DF_DefaultTaxPerDollar DEFAULT 0.087 FOR [DefaultTaxPerDollar]
ALTER TABLE [Config] ALTER COLUMN [DefaultTaxPerDollar] [decimal](19, 5) NOT NULL
I think I may have found a solution, to use the Sql()
method with some complex SQL inspired by this post. The problem stems from the fact that SQL Server uses constraints to implement defaults (OH! how I miss MySQL!) with a generated name for the constraint. So the Code First team could not simply change or remove/re-create the default value easily.
Default values can be NULL, or they can be a value that matches the data type of the column (number, text, date, for example). Let's see how to implement this in different databases and see some examples.
The DROP DEFAULT command is used to delete a DEFAULT constraint.
Removal of default constraints inspired by reverse migrations produced by Entity Framework for 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);
}
It's slightly shorter, but the usage is the same.
DropDefaultConstraint(TableName, "DefaultTaxPerDollar", q => Sql(q));
The Guid is used to make a unique variable name in case you are going to drop several constraints in one migration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With