question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Constraint not being re-created after being dropped automatically (changed in 6.2)

See original GitHub issue

If a table is created with a primary key default value of (newsequentialid()), and then in a subsequent migration that column is ALTERed, then the default will be removed and not recreated. This occurs in 6.2 and 6.3 but NOT in 6.1.

Model/Context Setup

    public class FooTable
    {
        public Guid Id { get; set; }
    }

    public class FooTableMap : EntityTypeConfiguration<FooTable>
    {
        public FooTableMap()
        {
           Property(t => t.Id).HasColumnName("FooId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }

    public class FooContext : DbContext
    {
        public DbSet<FooTable> Foos { get; set; }

        public FooContext() : base("EFContext")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.AddFromAssembly(typeof(FooTableMap).Assembly);
        }
    }

Repro

Create an initial migration, you get something like this:

    public partial class InitialCreate : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.FooTables",
                c => new
                    {
                        FooId = c.Guid(nullable: false, identity: true),  // <<< Identity == true!
                    })
                .PrimaryKey(t => t.FooId);
            
        }
        
        public override void Down()
        {
            DropTable("dbo.FooTables");
        }
    }

Run this migration and you will get the table with the default value as expected.

Now add a new migration like this:

    public partial class NewMigration : DbMigration
    {
        public override void Up()
        {
            DropPrimaryKey("dbo.FooTables");
            AlterColumn("dbo.FooTables", "FooId", c => c.Guid(nullable: false, identity: true));  // <<< IDENTITY is *still* true
            AddPrimaryKey("dbo.FooTables", "FooId");
        }
        
        public override void Down()
        {
        }
    }

The migration defines the column exactly as it was in the original migration. Run the migration:

  • On 6.1 the default value will still remain
  • On 6.2 the default value will be removed

The SQL in 6.1 looks like:

ALTER TABLE [dbo].[FooTables] ALTER COLUMN [FooId] [uniqueidentifier] NOT NULL

in 6.2 (and 6.3) it is:

SELECT @var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.FooTables')
AND col_name(parent_object_id, parent_column_id) = 'FooId';
IF @var0 IS NOT NULL
    EXECUTE('ALTER TABLE [dbo].[FooTables] DROP CONSTRAINT [' + @var0 + ']')
ALTER TABLE [dbo].[FooTables] ALTER COLUMN [FooId] [uniqueidentifier] NOT NULL

The drop contraint removes the default value, and nothing adds it back in.

This issues was introduced by this commit https://github.com/aspnet/EntityFramework6/pull/137/commits/15de49003c43365307408b408dc57252847f9803

Possible Fix Add an additional WHERE clause to the contraint sql to exclude default values? (AND type <> 'D' at the end)

Further technical details

EF version: 6.2 Database Provider: MSSQL Operating system: Windows 10 IDE: Visual Studio 2019 / Rider 2019.2 [EfMigrationTest.zip]

Complete repro solution (using EF6.2 - downgrade to 6.1 and re-run migrations to see the old SQL)

(https://github.com/aspnet/EntityFramework6/files/3609403/EfMigrationTest.zip)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
slovelycommented, Oct 17, 2019

Thank you. By the way - we upgraded a fairly large app from EF6.1 to EF6.3, moved from 4.6.1 to dotnetcore v3, and it was really easy. Also CPU usage appears to be nearly 50% less, with no effort spent on optimisations. Just a little “thank you” to offset the bug 😃

1reaction
slovelycommented, Oct 15, 2019

@ajcvickers - Fair enough 😃 I would guess it is pretty low-impact, especially as it already existed in 6.2. It’s possible some more people might upgrade from <6.1 to 6.3 for the .net core support though.

Just in case someone stumbles on this issue the workaround we did was to modify the migrations from:

AlterColumn("dbo.FooTables", "FooId", c => c.Guid(nullable: false, identity: true)); 

to:

AlterColumn("dbo.FooTables", "FooId", c => c.Guid(nullable: false, defaultValueSql: "newsequentialid()")); 

Please feel free to close, or if you think it’s worthwhile for me to create a PR with a possible fix (not looked at the migration code before so can’t promise I will manage it!)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Migration: Cannot add foreign key constraint - laravel
This error occurred for me because I created the migration table with the foreign key in it firstly before the key existed as...
Read more >
2 Setting Up The 6.2.x Database
This step does not occur in upgrade mode 3. Choose one of the following storage options: If you want the tables that are...
Read more >
Dropping and Recreating a Table - TechDocs - Broadcom Inc.
If the table to be recreated is empty, you need not define a new table. Instead, simply drop and redefine the table making...
Read more >
2021_10 Bundle
If you specified NORELY in the command, NORELY was ignored or an error was thrown. For existing constraints, you could not change the...
Read more >
New sketcher
New sketch is a huge change, but here are a couple of things that may help you: 1. The most important thing is...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found