Changing column default values in EF5 Code First

后端 未结 2 1761
时光取名叫无心
时光取名叫无心 2020-12-17 18:56

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 th

相关标签:
2条回答
  • 2020-12-17 19:32

    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.

    0 讨论(0)
  • 2020-12-17 19:42

    Here's a solution that was inspired by this post. It's not exactly an elegant method, but it works for me.

    
            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);
            }
    

    And in your migration, you can call it like this:

    DropDefaultConstraint(TableName, "DefaultTaxPerDollar", q => Sql(q));
    

    The reason for using the lamba is because you have to make three distinct calls to Sql(). I was never able to get this to work as one long query - tried many combinations of the keyword GO in many different places. I also tried reversing the logic on the first query so that the UDF only gets recreated if it does not exist, and it didn't work. I suppose recreating it every time is more robust anyway.

    0 讨论(0)
提交回复
热议问题