Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to flow custom annotations through to Migrations #10258

Open
Tracked by #22946
Rgl88 opened this issue Nov 10, 2017 · 2 comments
Open
Tracked by #22946

Make it easier to flow custom annotations through to Migrations #10258

Rgl88 opened this issue Nov 10, 2017 · 2 comments

Comments

@Rgl88
Copy link

Rgl88 commented Nov 10, 2017

Custom annotations on properties are not included in generated Up/Down migration, but they are correctly included in the BuildTargetModel method
I want reorder columns in up method via my custom 'DisplayOrder' annotation.

Consider the following example:
Custom Annotations added to

[DbContext(typeof(TestDbContext))]
[Migration("13960818210148_TestDb_Migration_v1.0")]
partial class TestDb_Migration_v10
{
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
               modelBuilder.Entity("St.Domain.Financial.Bank", b =>
                {
				    ...
						
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd();

                    b.Property<string>("Description")
                        .HasMaxLength(512)
                        .HasAnnotation("ColumnOrder", 4);

                    b.Property<string>("Name")
                        .IsRequired()
                        .HasMaxLength(128)
                        .HasAnnotation("ColumnOrder", 2);
                    b.ToTable("Bank");
					
					...
                });
        }
}

but not exist in:

public partial class TestDb_Migration_v10 : Migration
{
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Bank",
                columns: table => new
                {
				    ...
                    Id = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
                    Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false)
					...
                });
        }
}

C:\Users\User1>dotnet --info
.NET Command Line Tools (2.0.0)

Product Information:
Version: 2.0.0
Commit SHA-1 hash: cdcd1928c9

Runtime Environment:
OS Name: Windows
OS Version: 10.0.14393
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\2.0.0\

Microsoft .NET Core Shared Framework Host
Version : 2.0.0
Build : e8b8861ac7faf042c87a5c2f9f2d04c98b69f28d

@ajcvickers
Copy link
Member

@Rgl88 Annotations are only propagated to Migrations if they have been configured to do so. The reason for this is so that Migrations doesn't generate diffs and scaffold a new migration when any annotation changes, since many annotations only affect runtime behavior, not the database schema.

Currently this requires overriding and replacing the annotation provider for whichever database you are using. For example, for SQL Server:

public class CustomAnnotationProvider : SqlServerMigrationsAnnotationProvider
{
    public CustomAnnotationProvider(MigrationsAnnotationProviderDependencies dependencies) 
        : base(dependencies)
    {
    }

    public override IEnumerable<IAnnotation> For(IProperty property)
    {
        var baseAnnotations = base.For(property);

        var annotation = property.FindAnnotation("ColumnOrder");

        return annotation == null
            ? baseAnnotations
            : baseAnnotations.Concat(new[] { annotation });
    }
}

This must then be registered in OnConfiguring or AddDbContext:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .ReplaceService<IMigrationsAnnotationProvider, CustomAnnotationProvider>()
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=TestDatabase;ConnectRetryCount=0");

I'm re-purposing this bug to consider implementing an easier way of doing this.

@weitzhandler
Copy link
Contributor

weitzhandler commented Dec 26, 2018

@ajcvickers thanks for your helpful example!
Would be nice if the interaction between OnModelCreating and the migration process can be soften up a bit.
I opened a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants