From 26f3860c40a4f30d74da5c6611810a8ffc2fb6c3 Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Mon, 24 Feb 2025 11:12:27 +0100 Subject: [PATCH 1/7] Use Invariant Culture for ChangeType --- .../Scaffolding/Internal/SqlServerDatabaseModelFactory.cs | 2 +- .../Scaffolding/SqlServerDatabaseModelFactoryTest.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index 5bdf3af9087..dc3572b09a7 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -918,7 +918,7 @@ FROM [sys].[views] v { try { - return Convert.ChangeType(defaultValueSql, type); + return Convert.ChangeType(defaultValueSql, type, CultureInfo.InvariantCulture); } catch { diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index 7038c31e278..da300254f61 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -3939,6 +3939,7 @@ CREATE TABLE MyTable ( B decimal DEFAULT (0.0), C decimal DEFAULT (0), D decimal DEFAULT ((CONVERT ( ""decimal"", ( (1.1234) ) ))), + E decimal DEFAULT ((10.0)), );", Enumerable.Empty(), Enumerable.Empty(), @@ -3962,6 +3963,10 @@ D decimal DEFAULT ((CONVERT ( ""decimal"", ( (1.1234) ) ))), Assert.Equal("(CONVERT([decimal],(1.1234)))", column.DefaultValueSql); Assert.Equal((decimal)1.1234, column.DefaultValue); + column = columns.Single(c => c.Name == "E"); + Assert.Equal("((10.0))", column.DefaultValueSql); + Assert.Equal((decimal)10, column.DefaultValue); + var model = scaffoldingFactory.Create(dbModel, new ModelReverseEngineerOptions()); Assert.Equal(1, model.GetEntityTypes().Count()); }, From 7340fb6a9cfaa9bd31b79021a5113d080b13fde6 Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Mon, 24 Feb 2025 15:32:21 +0100 Subject: [PATCH 2/7] add fix to SQLite provider Add "international" tests --- .../Internal/SqliteDatabaseModelFactory.cs | 2 +- .../SqlServerDatabaseModelFactoryTest.cs | 54 ++++++++++++++++++ .../SqliteDatabaseModelFactoryTest.cs | 57 ++++++++++++++++++- 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index b67f8571b42..a6bd364f4c9 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -429,7 +429,7 @@ private void ParseClrDefaults(DatabaseTable table) { try { - column.DefaultValue = Convert.ChangeType(defaultValueSql, type); + column.DefaultValue = Convert.ChangeType(defaultValueSql, type, CultureInfo.InvariantCulture); } catch { diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index da300254f61..684cf24c12f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -3972,6 +3972,60 @@ E decimal DEFAULT ((10.0)), }, "DROP TABLE MyTable;"); + [ConditionalFact] + public void Simple_decimal_literals_are_parsed_for_HasDefaultValue_with_Danish_locale() + { + try + { + var currentCulture = CultureInfo.CurrentCulture; + CultureInfo.CurrentCulture = new CultureInfo("da-DK"); + Test( + @" +CREATE TABLE MyTable ( + Id int, + A decimal DEFAULT -1.1111, + B decimal DEFAULT (0.0), + C decimal DEFAULT (0), + D decimal DEFAULT ((CONVERT ( ""decimal"", ( (1.1234) ) ))), + E decimal DEFAULT ((10.0)), +);", + Enumerable.Empty(), + Enumerable.Empty(), + (dbModel, scaffoldingFactory) => + { + var columns = dbModel.Tables.Single().Columns; + + var column = columns.Single(c => c.Name == "A"); + Assert.Equal("((-1.1111))", column.DefaultValueSql); + Assert.Equal((decimal)-1.1111, column.DefaultValue); + + column = columns.Single(c => c.Name == "B"); + Assert.Equal("((0.0))", column.DefaultValueSql); + Assert.Equal((decimal)0, column.DefaultValue); + + column = columns.Single(c => c.Name == "C"); + Assert.Equal("((0))", column.DefaultValueSql); + Assert.Equal((decimal)0, column.DefaultValue); + + column = columns.Single(c => c.Name == "D"); + Assert.Equal("(CONVERT([decimal],(1.1234)))", column.DefaultValueSql); + Assert.Equal((decimal)1.1234, column.DefaultValue); + + column = columns.Single(c => c.Name == "E"); + Assert.Equal("((10.0))", column.DefaultValueSql); + Assert.Equal((decimal)10, column.DefaultValue); + + var model = scaffoldingFactory.Create(dbModel, new ModelReverseEngineerOptions()); + Assert.Equal(1, model.GetEntityTypes().Count()); + }, + "DROP TABLE MyTable;"); + } + finally + { + CultureInfo.CurrentCulture = currentCulture; + } + } + [ConditionalFact] public void Simple_bool_literals_are_parsed_for_HasDefaultValue() => Test( diff --git a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs index 23152fbf7cb..09c134f97b0 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs @@ -850,9 +850,10 @@ CREATE TABLE MyTable ( Id int, A decimal DEFAULT '-1.1111', B decimal DEFAULT ('0.0'), - C decimal DEFAULT ('0')); + C decimal DEFAULT ('0')), + D decimal DEFAULT ('10.0')); -INSERT INTO MyTable VALUES (1, '1.1', '1.2', '1.3');", +INSERT INTO MyTable VALUES (1, '1.1', '1.2', '1.3', '1.4');", Enumerable.Empty(), Enumerable.Empty(), dbModel => @@ -870,9 +871,61 @@ B decimal DEFAULT ('0.0'), column = columns.Single(c => c.Name == "C"); Assert.Equal("'0'", column.DefaultValueSql); Assert.Equal((decimal)0, column.DefaultValue); + + column = columns.Single(c => c.Name == "D"); + Assert.Equal("'10'", column.DefaultValueSql); + Assert.Equal((decimal)10, column.DefaultValue); }, "DROP TABLE MyTable;"); + [ConditionalFact] + public void Simple_decimal_literals_are_parsed_for_HasDefaultValue_with_Danish_locale() + { + try + { + var culture = CultureInfo.CurrentCulture; + CultureInfo.CurrentCulture = new CultureInfo("da-DK"); + + Test( + @" +CREATE TABLE MyTable ( + Id int, + A decimal DEFAULT '-1.1111', + B decimal DEFAULT ('0.0'), + C decimal DEFAULT ('0')), + D decimal DEFAULT ('10.0')); + +INSERT INTO MyTable VALUES (1, '1.1', '1.2', '1.3', '1.4');", + Enumerable.Empty(), + Enumerable.Empty(), + dbModel => + { + var columns = dbModel.Tables.Single().Columns; + + var column = columns.Single(c => c.Name == "A"); + Assert.Equal("'-1.1111'", column.DefaultValueSql); + Assert.Equal((decimal)-1.1111, column.DefaultValue); + + column = columns.Single(c => c.Name == "B"); + Assert.Equal("'0.0'", column.DefaultValueSql); + Assert.Equal((decimal)0, column.DefaultValue); + + column = columns.Single(c => c.Name == "C"); + Assert.Equal("'0'", column.DefaultValueSql); + Assert.Equal((decimal)0, column.DefaultValue); + + column = columns.Single(c => c.Name == "D"); + Assert.Equal("'10'", column.DefaultValueSql); + Assert.Equal((decimal)10, column.DefaultValue); + }, + "DROP TABLE MyTable;"); + } + finally + { + CultureInfo.CurrentCulture = culture; + } + } + [ConditionalFact] public void Simple_bool_literals_are_parsed_for_HasDefaultValue() => Test( From 17fdd15b4399004cc4cdd3dfd5d51c9521895808 Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Mon, 24 Feb 2025 21:20:33 +0100 Subject: [PATCH 3/7] fix build --- .../Scaffolding/SqlServerDatabaseModelFactoryTest.cs | 1 + .../Scaffolding/SqliteDatabaseModelFactoryTest.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index 684cf24c12f..8d957cd5710 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Globalization; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; using Microsoft.EntityFrameworkCore.SqlServer.Diagnostics.Internal; diff --git a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs index 09c134f97b0..bfad74513e8 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Globalization; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; From 35fbecc3a026bf516c75d901ee37ed78e418f58f Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Tue, 25 Feb 2025 09:06:38 +0100 Subject: [PATCH 4/7] fix build --- .../Scaffolding/Internal/SqliteDatabaseModelFactory.cs | 1 + .../Scaffolding/SqlServerDatabaseModelFactoryTest.cs | 3 ++- .../Scaffolding/SqliteDatabaseModelFactoryTest.cs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index a6bd364f4c9..fbb9fb57721 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Data; +using System.Globalization; using System.Text; using System.Text.RegularExpressions; using Microsoft.Data.Sqlite; diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index 8d957cd5710..531ee80a99b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -3976,9 +3976,10 @@ E decimal DEFAULT ((10.0)), [ConditionalFact] public void Simple_decimal_literals_are_parsed_for_HasDefaultValue_with_Danish_locale() { + var currentCulture = CultureInfo.CurrentCulture; + try { - var currentCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo("da-DK"); Test( @" diff --git a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs index bfad74513e8..ca1739730d4 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs @@ -882,9 +882,10 @@ C decimal DEFAULT ('0')), [ConditionalFact] public void Simple_decimal_literals_are_parsed_for_HasDefaultValue_with_Danish_locale() { + var culture = CultureInfo.CurrentCulture; + try { - var culture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo("da-DK"); Test( From 52d019e513f6149dac205ffe21fb3938b3d9ad9d Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Tue, 25 Feb 2025 09:58:35 +0100 Subject: [PATCH 5/7] fix syntax --- .../Scaffolding/SqliteDatabaseModelFactoryTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs index ca1739730d4..bd496591aa1 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs @@ -851,7 +851,7 @@ CREATE TABLE MyTable ( Id int, A decimal DEFAULT '-1.1111', B decimal DEFAULT ('0.0'), - C decimal DEFAULT ('0')), + C decimal DEFAULT ('0'), D decimal DEFAULT ('10.0')); INSERT INTO MyTable VALUES (1, '1.1', '1.2', '1.3', '1.4');", @@ -894,7 +894,7 @@ CREATE TABLE MyTable ( Id int, A decimal DEFAULT '-1.1111', B decimal DEFAULT ('0.0'), - C decimal DEFAULT ('0')), + C decimal DEFAULT ('0'), D decimal DEFAULT ('10.0')); INSERT INTO MyTable VALUES (1, '1.1', '1.2', '1.3', '1.4');", From 6ba97bf11e763949c27f1c54e755532047227267 Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Tue, 25 Feb 2025 10:24:10 +0100 Subject: [PATCH 6/7] fix test --- .../Scaffolding/SqliteDatabaseModelFactoryTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs index bd496591aa1..23d23c12294 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Scaffolding/SqliteDatabaseModelFactoryTest.cs @@ -874,7 +874,7 @@ C decimal DEFAULT ('0'), Assert.Equal((decimal)0, column.DefaultValue); column = columns.Single(c => c.Name == "D"); - Assert.Equal("'10'", column.DefaultValueSql); + Assert.Equal("'10.0'", column.DefaultValueSql); Assert.Equal((decimal)10, column.DefaultValue); }, "DROP TABLE MyTable;"); @@ -917,7 +917,7 @@ C decimal DEFAULT ('0'), Assert.Equal((decimal)0, column.DefaultValue); column = columns.Single(c => c.Name == "D"); - Assert.Equal("'10'", column.DefaultValueSql); + Assert.Equal("'10.0'", column.DefaultValueSql); Assert.Equal((decimal)10, column.DefaultValue); }, "DROP TABLE MyTable;"); From 796295d62bbf1d4773af7f863cc84b26aac3a0d0 Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Wed, 26 Feb 2025 12:41:09 +0100 Subject: [PATCH 7/7] Fix one more localization bug --- .../Scaffolding/Internal/SqliteDatabaseModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index fbb9fb57721..15289bf3c9c 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -472,7 +472,7 @@ private void ParseClrDefaults(DatabaseTable table) column.DefaultValue = dateTimeOffset; } else if (type == typeof(decimal) - && decimal.TryParse(defaultValueSql, out var decimalValue)) + && decimal.TryParse(defaultValueSql, CultureInfo.InvariantCulture, out var decimalValue)) { column.DefaultValue = decimalValue; }