From 955a818e7fb2869f2c0c99d6c9b8fb9e1b872222 Mon Sep 17 00:00:00 2001 From: Jay Harris Date: Fri, 21 Jan 2022 16:44:26 -0800 Subject: [PATCH] fix(efcore): correct column type mismatch with CSVs correct mismatch on CSVs, such as decimal(18, 2) vs decimal(18,2) --- .../SchemaValidator.cs | 2 +- .../SchemaValidator.cs | 2 +- .../SchemaValidator.cs | 4 +- .../MigrationsMissingForeignKeys.cs | 31 ++++++++++--- .../Migrations/MigrationsMissingIndexes.cs | 41 +++++++++++++---- .../Migrations/MigrationsMissingViews.cs | 44 ++++++++++++++----- ...igrationsWithIncorrectColumnNullability.cs | 44 ++++++++++++++----- .../MigrationsWithIncorrectColumnTypes.cs | 44 ++++++++++++++----- .../Migrations/ValidIdentityMigrations.cs | 44 ++++++++++++++----- .../Support/TableBasedEntity.cs | 4 ++ 10 files changed, 202 insertions(+), 58 deletions(-) diff --git a/src/entityframeworkcore/src/entityframeworkcore2.validation/SchemaValidator.cs b/src/entityframeworkcore/src/entityframeworkcore2.validation/SchemaValidator.cs index 577c4dd..3832853 100644 --- a/src/entityframeworkcore/src/entityframeworkcore2.validation/SchemaValidator.cs +++ b/src/entityframeworkcore/src/entityframeworkcore2.validation/SchemaValidator.cs @@ -66,7 +66,7 @@ public class SchemaValidator { } var columnTypesMatch = - dbColumn.StoreType.Equals(entityColumn.ColumnType, StringComparison.OrdinalIgnoreCase); + dbColumn.StoreType.Replace(", ",",").Equals(entityColumn.ColumnType.Replace(", ",","), StringComparison.OrdinalIgnoreCase); if (!columnTypesMatch) { valErrors.Add( $"Column type mismatch in {entityTable.TableName} for column {entityColumn.ColumnName}. Found: {dbColumn.StoreType.ToLowerInvariant()}, Expected {entityColumn.ColumnType.ToLowerInvariant()}"); diff --git a/src/entityframeworkcore/src/entityframeworkcore3.validation/SchemaValidator.cs b/src/entityframeworkcore/src/entityframeworkcore3.validation/SchemaValidator.cs index 62c6f6a..55f53a7 100644 --- a/src/entityframeworkcore/src/entityframeworkcore3.validation/SchemaValidator.cs +++ b/src/entityframeworkcore/src/entityframeworkcore3.validation/SchemaValidator.cs @@ -66,7 +66,7 @@ public class SchemaValidator { } var columnTypesMatch = - dbColumn.StoreType.Equals(persistedColumn.GetColumnType(), StringComparison.OrdinalIgnoreCase); + dbColumn.StoreType.Replace(", ",",").Equals(persistedColumn.GetColumnType().Replace(", ",","), StringComparison.OrdinalIgnoreCase); if (!columnTypesMatch) { valErrors.Add( $"Column type mismatch in {persistedType.GetTableName()} for column {persistedColumn.GetColumnName()}. Found: {dbColumn.StoreType.ToLowerInvariant()}, Expected {persistedColumn.GetColumnType().ToLowerInvariant()}"); diff --git a/src/entityframeworkcore/src/entityframeworkcore5.validation/SchemaValidator.cs b/src/entityframeworkcore/src/entityframeworkcore5.validation/SchemaValidator.cs index 0257da7..9f58408 100644 --- a/src/entityframeworkcore/src/entityframeworkcore5.validation/SchemaValidator.cs +++ b/src/entityframeworkcore/src/entityframeworkcore5.validation/SchemaValidator.cs @@ -70,7 +70,7 @@ public class SchemaValidator { } var columnTypesMatch = - dbColumn.StoreType.Equals(persistedColumn.GetColumnType(), StringComparison.OrdinalIgnoreCase); + dbColumn.StoreType.Replace(", ",",").Equals(persistedColumn.GetColumnType().Replace(", ",","), StringComparison.OrdinalIgnoreCase); if (!columnTypesMatch) { valErrors.Add( $"Column type mismatch in {persistedType.GetTableName()} for column {persistedColumn.GetColumnName(StoreObjectIdentifier.Table(persistedType.GetTableName(), null))}. Found: {dbColumn.StoreType.ToLowerInvariant()}, Expected {persistedColumn.GetColumnType().ToLowerInvariant()}"); @@ -90,7 +90,7 @@ public class SchemaValidator { } var columnTypesMatch = - dbColumn.StoreType.Equals(persistedColumn.GetColumnType(), StringComparison.OrdinalIgnoreCase); + dbColumn.StoreType.Replace(", ",",").Equals(persistedColumn.GetColumnType().Replace(", ",","), StringComparison.OrdinalIgnoreCase); if (!columnTypesMatch) { valErrors.Add( $"Column type mismatch in {persistedType.GetViewName()} for column {persistedColumn.GetColumnName(StoreObjectIdentifier.View(persistedType.GetViewName(), null))}. Found: {dbColumn.StoreType.ToLowerInvariant()}, Expected {persistedColumn.GetColumnType().ToLowerInvariant()}"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingForeignKeys.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingForeignKeys.cs index 7914b0b..9e9e685 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingForeignKeys.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingForeignKeys.cs @@ -109,11 +109,32 @@ public class MigrationsMissingForeignKeys : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", col => col.AsInt32().NotNullable().Indexed("IX_TableBasedEntity_RoleId")) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId")) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 2).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId")) + ; + }); Execute.Sql(@"CREATE VIEW ViewBasedEntities AS SELECT Id, Field, RoleId FROM TableBasedEntity"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingIndexes.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingIndexes.cs index d48c07b..50ebcde 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingIndexes.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingIndexes.cs @@ -113,15 +113,38 @@ public class MigrationsMissingIndexes : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", - col => col.AsInt32() - .NotNullable() - .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", "AspNetRoles", "Id") - .OnDelete(Rule.Cascade)) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 2).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); Execute.Sql(@"CREATE VIEW ViewBasedEntities AS SELECT Id, Field, RoleId FROM TableBasedEntity"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingViews.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingViews.cs index e6adcdc..7455827 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingViews.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsMissingViews.cs @@ -128,16 +128,40 @@ public class MigrationsMissingViews : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", - col => col.AsInt32() - .NotNullable() - .Indexed("IX_TableBasedEntity_RoleId") - .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", "AspNetRoles", "Id") - .OnDelete(Rule.Cascade)) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 2).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); Create.Table("TableBasedChildEntity") .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedChildEntity")) diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnNullability.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnNullability.cs index 7d4e633..812b975 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnNullability.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnNullability.cs @@ -128,16 +128,40 @@ public class MigrationsWithIncorrectColumnNullability : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", - col => col.AsInt32() - .NotNullable() - .Indexed("IX_TableBasedEntity_RoleId") - .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", "AspNetRoles", "Id") - .OnDelete(Rule.Cascade)) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).Nullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 2).Nullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); Execute.Sql(@"CREATE VIEW ViewBasedEntities AS SELECT Id, Field, RoleId FROM TableBasedEntity"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnTypes.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnTypes.cs index 9fd6d7c..69c7df2 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnTypes.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/MigrationsWithIncorrectColumnTypes.cs @@ -128,16 +128,40 @@ public class MigrationsWithIncorrectColumnTypes : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", - col => col.AsInt32() - .NotNullable() - .Indexed("IX_TableBasedEntity_RoleId") - .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", "AspNetRoles", "Id") - .OnDelete(Rule.Cascade)) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 3).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); Execute.Sql(@"CREATE VIEW ViewBasedEntities AS SELECT Id, Field, RoleId FROM TableBasedEntity"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/ValidIdentityMigrations.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/ValidIdentityMigrations.cs index 8ef6403..7b4ce0b 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/ValidIdentityMigrations.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/Migrations/ValidIdentityMigrations.cs @@ -128,16 +128,40 @@ public class ValidIdentityMigrations : Migration { .WithColumn("Value", col => col.AsStringMax().Nullable()) ; - Create.Table("TableBasedEntity") - .WithColumn("Id", col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) - .WithColumn("Field", col => col.AsString(256).Nullable()) - .WithColumn("RoleId", - col => col.AsInt32() - .NotNullable() - .Indexed("IX_TableBasedEntity_RoleId") - .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", "AspNetRoles", "Id") - .OnDelete(Rule.Cascade)) - ; + IfDatabase(dbType => string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsString(20000).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); + IfDatabase(dbType => !string.Equals(dbType, "SQLite-Test", StringComparison.InvariantCultureIgnoreCase)) + .Delegate(() => { + Create.Table("TableBasedEntity") + .WithColumn("Id", + col => col.AsInt32().NotNullable().PrimaryKey("PK_TableBasedEntity")) + .WithColumn("Field", col => col.AsString(256).Nullable()) + .WithColumn("NumberValue", col => col.AsDecimal(18, 2).NotNullable()) + .WithColumn("RoleId", + col => col.AsInt32() + .NotNullable() + .Indexed("IX_TableBasedEntity_RoleId") + .ForeignKey("FK_TableBasedEntity_AspNetRoles_RoleId", + "AspNetRoles", + "Id") + .OnDelete(Rule.Cascade)) + ; + }); Execute.Sql(@"CREATE VIEW ViewBasedEntities AS SELECT Id, Field, RoleId FROM TableBasedEntity"); diff --git a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/TableBasedEntity.cs b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/TableBasedEntity.cs index 337dd4b..448241a 100644 --- a/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/TableBasedEntity.cs +++ b/src/entityframeworkcore/test/entityframeworkcore2.validation.tests/Support/TableBasedEntity.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using Microsoft.AspNetCore.Identity; namespace Aranasoft.Cobweb.EntityFrameworkCore.Validation.Tests.Support { @@ -10,6 +11,9 @@ public class TableBasedEntity { [MaxLength(256)] public string Field { get; set; } + [Column("NumberValue")] + public decimal Number { get; set; } + [Required] public IdentityRole Role { get; set; } }