From 20dfc050459e7ba92fa13941e0849f791f65936d Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 25 Jun 2019 07:38:26 -0700 Subject: [PATCH] Fix issue with SQLite migration snapshot needing a type mapping Initial fix for #16239 Required to unblock https://github.com/aspnet/AspNetCore/pull/11531#issuecomment-505289690 --- .../SqliteMigrationsAnnotationProvider.cs | 2 +- .../MigrationsTestBase.cs | 3 + .../MigrationsSqlServerTest.cs | 101 ++++++++++++++++++ .../MigrationsSqliteTest.cs | 100 +++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) diff --git a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationsAnnotationProvider.cs b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationsAnnotationProvider.cs index e16a833377c..b844fed7e62 100644 --- a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationsAnnotationProvider.cs +++ b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationsAnnotationProvider.cs @@ -84,6 +84,6 @@ public override IEnumerable For(IProperty property) } private static bool HasConverter(IProperty property) - => property.GetTypeMapping().Converter != null; + => property.FindMapping()?.Converter != null; } } diff --git a/test/EFCore.Relational.Specification.Tests/MigrationsTestBase.cs b/test/EFCore.Relational.Specification.Tests/MigrationsTestBase.cs index 5940932bb9f..35aa6076c4a 100644 --- a/test/EFCore.Relational.Specification.Tests/MigrationsTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/MigrationsTestBase.cs @@ -354,6 +354,9 @@ protected virtual Task ExecuteAsync(IServiceProvider services, Action(); + var operations = modelDiffer.GetDifferences(sourceModel, targetModel); + + Assert.Equal(0, operations.Count); + } + } + + public class BloggingContextModelSnapshot22 : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("ModelSnapshot22.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("ModelSnapshot22.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("BlogId"); + + b.Property("Content"); + + b.Property("EditDate"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("BlogId"); + + b.ToTable("Post"); + }); + + modelBuilder.Entity("ModelSnapshot22.Post", b => + { + b.HasOne("ModelSnapshot22.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogId"); + }); +#pragma warning restore 612, 618 + } + } + } +} + +namespace ModelSnapshot22 +{ + public class Blog + { + public int Id { get; set; } + public string Name { get; set; } + + public ICollection Posts { get; set; } + } + + public class Post + { + public int Id { get; set; } + public string Title { get; set; } + public string Content { get; set; } + public DateTime EditDate { get; set; } + + public Blog Blog { get; set; } + } + + public class BloggingContext : DbContext + { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0"); + + public DbSet Blogs { get; set; } } } diff --git a/test/EFCore.Sqlite.FunctionalTests/MigrationsSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/MigrationsSqliteTest.cs index cac1831bc28..517cb6b6560 100644 --- a/test/EFCore.Sqlite.FunctionalTests/MigrationsSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/MigrationsSqliteTest.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Data.Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; @@ -298,5 +300,103 @@ FROM sqlite_master return builder.ToString(); } + + public override void Can_diff_against_2_2_model() + { + using (var context = new ModelSnapshot22.BloggingContext()) + { + var snapshot = new BloggingContextModelSnapshot22(); + var sourceModel = snapshot.Model; + var targetModel = context.Model; + + var modelDiffer = context.GetService(); + var operations = modelDiffer.GetDifferences(sourceModel, targetModel); + + Assert.Equal(0, operations.Count); + } + } + + public class BloggingContextModelSnapshot22 : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + + modelBuilder.Entity( + "ModelSnapshot22.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity( + "ModelSnapshot22.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BlogId"); + + b.Property("Content"); + + b.Property("EditDate"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("BlogId"); + + b.ToTable("Post"); + }); + + modelBuilder.Entity( + "ModelSnapshot22.Post", b => + { + b.HasOne("ModelSnapshot22.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogId"); + }); +#pragma warning restore 612, 618 + } + } } } + +namespace ModelSnapshot22 +{ + public class Blog + { + public int Id { get; set; } + public string Name { get; set; } + + public ICollection Posts { get; set; } + } + + public class Post + { + public int Id { get; set; } + public string Title { get; set; } + public string Content { get; set; } + public DateTime EditDate { get; set; } + + public Blog Blog { get; set; } + } + + public class BloggingContext : DbContext + { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseSqlite("DataSource=Test.db"); + + public DbSet Blogs { get; set; } + } +} +