EF 4.3.1 Migration Exception - AlterColumn defaultValueSql creates same default constraint name for different tables

后端 未结 3 1760
再見小時候
再見小時候 2020-12-06 14:03

I have a DB that I created using the OOB database initializer, and I am using Code First with EF 4.3.1.

I wanted to take advantage of the new \"IgnoreChanges\" flag

3条回答
  •  情歌与酒
    2020-12-06 14:28

    It seems it's a known bug: msdn forums

    Andrew J Peters Microsoft (MSFT) replied:

    Thanks for reporting this. The issue will be fixed for RTM.

    A possible workaround is to initially make the column nullable, which will prevent Migrations from generating the extra DEFAULT constraint. Once the column is created, then it can be altered back to non-nullable.

    But it's definitelly not fixed in EF 4.3.1. Here is relevant part of the source:

    // Type: System.Data.Entity.Migrations.Sql.SqlServerMigrationSqlGenerator
    // Assembly: EntityFramework, Version=4.3.1.0, 
    // Culture=neutral, PublicKeyToken=b77a5c561934e089
    namespace System.Data.Entity.Migrations.Sql
    {
      public class SqlServerMigrationSqlGenerator : MigrationSqlGenerator
      {
         protected virtual void Generate(AlterColumnOperation alterColumnOperation)
         {
          //...
          writer.Write("ALTER TABLE ");
          writer.Write(this.Name(alterColumnOperation.Table));
          writer.Write(" ADD CONSTRAINT DF_");
          writer.Write(column.Name);
          writer.Write(" DEFAULT ");
          //...
    

    So EF doesn't try to make the constraint name unique.

    You should try the workaround and report it as a bug.

    EDIT: I've just realized that above mentioned Generate method is virtual so in the worst case you can inherit from SqlServerMigrationSqlGenerator and fix the SQL generation and set it as the sql generator in Configuration.cs:

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        SetSqlGenerator("System.Data.SqlClient", 
            new MyFixedSqlServerMigrationSqlGenerator());
    }
    

    EDIT 2:

    I think the best thing to do until it fixed to fall back to raw SQL:

    public override void Up()
    {
        Sql(@"ALTER TABLE [CustomerLocations] ADD CONSTRAINT 
            DF_CustomerLocations_DateLastUpdated 
            DEFAULT GETDATE() FOR [DateLastUpdated]");
        Sql(@"ALTER TABLE [CustomerLocations] ALTER COLUMN 
            [DateLastUpdated] [datetime]");
        //...
    }
    

提交回复
热议问题