First code migration failed due to default constraint

You have a problem with changing the type of a property in an entity, a default constraint was created, but EF does not remove it when the column changes, so the update database is down.

The object previously had a DateTime property.

public DateTime ImportDate { get; set; }

      

As a result of migration, it contained this in it Up()

method

AddColumn("dbo.Table", "ImportDate", c => c.DateTime(nullable: false));

      

However, it also created a default constraint

ALTER TABLE [dbo].[Table] ADD  DEFAULT ('1900-01-01T00:00:00.000') FOR [ImportDate]

      

Imported ImportDate to DateTimeOffset

public DateTimeOffset ImportDate { get; set; }

      

And as a result of the migration there is an AlterColumn

AlterColumn("dbo.Table", "ImportDate", c => c.DateTimeOffset(nullable: false, precision: 7));

      

However, this fails because there is a default constraint.

The only way I can think of is to use Sql(...)

with DROP CONSTRAINT, however, CONSTRAINT has a seemingly random name DF__Table__Import__5441852A

, so hard-coded SQL won't work everywhere.

Thoughts?

+3


source to share


2 answers


You can create an extension and use it in the generated migration:

 internal static class MigrationExtensions
    {
        public static void DeleteDefaultContraint(this IDbMigration migration, string tableName, string colName, bool suppressTransaction = false)
        {
            var sql = new SqlOperation(String.Format(@"DECLARE @SQL varchar(1000)
                SET @SQL='ALTER TABLE {0} DROP CONSTRAINT ['+(SELECT name
                FROM sys.default_constraints
                WHERE parent_object_id = object_id('{0}')
                AND col_name(parent_object_id, parent_column_id) = '{1}')+']';
                PRINT @SQL;
                EXEC(@SQL);", tableName, colName)) { SuppressTransaction = suppressTransaction };
            migration.AddOperation(sql);
        }
    }

      

And used like this



this.DeleteDefaultContraint("dbo.Table", "ImportDate");

      

From this post: Group in LINQ

+8


source


Your best bet is to fix the problem permanently.

You can implement a custom sql generator class derived from SqlServerMigrationSqlGenerator from the System.Data.Entity.SqlServer namespace:

using System.Data.Entity.Migrations.Model;
using System.Data.Entity.SqlServer;

namespace System.Data.Entity.Migrations.Sql{
    internal class FixedSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator {
        protected override void Generate(AlterColumnOperation alterColumnOperation){
            ColumnModel column = alterColumnOperation.Column;
            var sql = String.Format(@"DECLARE @ConstraintName varchar(1000);
            DECLARE @sql varchar(1000);
            SELECT @ConstraintName = name   FROM sys.default_constraints
                WHERE parent_object_id = object_id('{0}')
                AND col_name(parent_object_id, parent_column_id) = '{1}';
            IF(@ConstraintName is NOT Null)
                BEGIN
                set @sql='ALTER TABLE {0} DROP CONSTRAINT [' + @ConstraintName+ ']';
            exec(@sql);
            END", alterColumnOperation.Table, column.Name);
                this.Statement(sql);
            base.Generate(alterColumnOperation);
            return;
        }
        protected override void Generate(DropColumnOperation dropColumnOperation){
            var sql = String.Format(@"DECLARE @SQL varchar(1000)
                SET @SQL='ALTER TABLE {0} DROP CONSTRAINT [' + (SELECT name
                    FROM sys.default_constraints
                    WHERE parent_object_id = object_id('{0}')
                    AND col_name(parent_object_id, parent_column_id) = '{1}') + ']';
            PRINT @SQL;
                EXEC(@SQL); ", dropColumnOperation.Table, dropColumnOperation.Name);

                    this.Statement(sql);
            base.Generate(dropColumnOperation);
        }
    }
}

      



and set this config:

internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;

        SetSqlGenerator("System.Data.SqlClient", new FixedSqlServerMigrationSqlGenerator ());
    }
    ...
}

      

+3


source







All Articles