Skip to content

Commit 5937c95

Browse files
committed
Fix for temp tables having default values with ValueConverters
1 parent 1ab93dd commit 5937c95

File tree

5 files changed

+63
-11
lines changed

5 files changed

+63
-11
lines changed

src/Thinktecture.EntityFrameworkCore.SqlServer/EntityFrameworkCore/TempTables/SqlServerTempTableCreator.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,20 @@ private string GetColumnsDefinitions(SqlServerTempTableCreatorCacheKey options)
246246
{
247247
sb.Append(" DEFAULT (").Append(defaultValueSql).Append(')');
248248
}
249-
else if (property.Property.TryGetDefaultValue(storeObject.Value, out var defaultValue))
249+
else if (property.Property.TryGetDefaultValue(storeObject.Value, out var defaultValue) && defaultValue is not null)
250250
{
251-
var mappingForValue = _typeMappingSource.GetMappingForValue(defaultValue);
252-
sb.Append(" DEFAULT ").Append(mappingForValue.GenerateSqlLiteral(defaultValue));
251+
var converter = property.Property.GetValueConverter();
252+
253+
if (converter is not null)
254+
defaultValue = converter.ConvertToProvider(defaultValue);
255+
256+
if (defaultValue is not null)
257+
{
258+
var mappingForValue = _typeMappingSource.FindMapping(defaultValue.GetType(), columnType)
259+
?? _typeMappingSource.GetMappingForValue(defaultValue);
260+
261+
sb.Append(" DEFAULT ").Append(mappingForValue.GenerateSqlLiteral(defaultValue));
262+
}
253263
}
254264

255265
isFirst = false;

src/Thinktecture.EntityFrameworkCore.Sqlite/EntityFrameworkCore/TempTables/SqliteTempTableCreator.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@ private string GetColumnsDefinitions(SqliteTempTableCreatorCacheKey options)
133133

134134
storeObject ??= property.GetStoreObject();
135135
var columnName = property.GetColumnName(storeObject.Value);
136+
var columnType = property.Property.GetColumnType(storeObject.Value);
136137

137138
sb.Append("\t\t")
138139
.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)).Append(' ')
139-
.Append(property.Property.GetColumnType(storeObject.Value))
140+
.Append(columnType)
140141
.Append(property.Property.IsNullable ? " NULL" : " NOT NULL");
141142

142143
if (property.Property.IsAutoIncrement())
@@ -157,10 +158,20 @@ private string GetColumnsDefinitions(SqliteTempTableCreatorCacheKey options)
157158
{
158159
sb.Append(" DEFAULT (").Append(defaultValueSql).Append(')');
159160
}
160-
else if (property.Property.TryGetDefaultValue(storeObject.Value, out var defaultValue))
161+
else if (property.Property.TryGetDefaultValue(storeObject.Value, out var defaultValue) && defaultValue is not null)
161162
{
162-
var mappingForValue = _typeMappingSource.GetMappingForValue(defaultValue);
163-
sb.Append(" DEFAULT ").Append(mappingForValue.GenerateSqlLiteral(defaultValue));
163+
var converter = property.Property.GetValueConverter();
164+
165+
if (converter is not null)
166+
defaultValue = converter.ConvertToProvider(defaultValue);
167+
168+
if (defaultValue is not null)
169+
{
170+
var mappingForValue = _typeMappingSource.FindMapping(defaultValue.GetType(), columnType)
171+
?? _typeMappingSource.GetMappingForValue(defaultValue);
172+
173+
sb.Append(" DEFAULT ").Append(mappingForValue.GenerateSqlLiteral(defaultValue));
174+
}
164175
}
165176

166177
isFirst = false;

tests/Thinktecture.EntityFrameworkCore.SqlServer.Tests/EntityFrameworkCore/TempTables/SqlServerTempTableCreatorTests/CreateTempTableAsync.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,20 @@ public async Task Should_create_temp_table_with_string()
560560
ValidateColumn(columns[0], nameof(TempTable<string>.Column1), "nvarchar", false);
561561
}
562562

563+
[Fact]
564+
public async Task Should_create_temp_table_with_converter_and_default_value()
565+
{
566+
ConfigureModel = builder => builder.ConfigureTempTable<ConvertibleClass>()
567+
.Property(t => t.Column1)
568+
.HasConversion(c => c.Key, k => new ConvertibleClass(k))
569+
.HasDefaultValue(new ConvertibleClass(1));
570+
571+
await using var tempTable = await SUT.CreateTempTableAsync(ActDbContext.GetEntityType<TempTable<ConvertibleClass>>(), _optionsWithNonUniqueName);
572+
573+
var columns = AssertDbContext.GetTempTableColumns<TempTable<ConvertibleClass>>().ToList();
574+
ValidateColumn(columns[0], nameof(TempTable<ConvertibleClass>.Column1), "int", false, defaultValue: "((1))");
575+
}
576+
563577
[Fact]
564578
public async Task Should_create_temp_table_with_string_with_max_length()
565579
{
@@ -694,13 +708,15 @@ private static void ValidateColumn(
694708
bool isNullable,
695709
byte? numericPrecision = null,
696710
int? numericScale = null,
697-
int? charMaxLength = null)
711+
int? charMaxLength = null,
712+
string? defaultValue = null)
698713
{
699714
ArgumentNullException.ThrowIfNull(column);
700715

701716
column.COLUMN_NAME.Should().Be(name);
702717
column.DATA_TYPE.Should().Be(type);
703718
column.IS_NULLABLE.Should().Be(isNullable ? "YES" : "NO");
719+
column.COLUMN_DEFAULT.Should().Be(defaultValue);
704720

705721
if (numericPrecision.HasValue)
706722
column.NUMERIC_PRECISION.Should().Be(numericPrecision.Value);

tests/Thinktecture.EntityFrameworkCore.Sqlite.Tests/EntityFrameworkCore/TempTables/SqliteTempTableCreatorTests/CreateTempTableAsync.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,20 @@ public async Task Should_create_temp_table_with_string()
602602
ValidateColumn(columns[0], nameof(TempTable<string>.Column1), "TEXT", false);
603603
}
604604

605+
[Fact]
606+
public async Task Should_create_temp_table_with_converter_and_default_value()
607+
{
608+
ConfigureModel = builder => builder.ConfigureTempTable<ConvertibleClass>()
609+
.Property(t => t.Column1)
610+
.HasConversion(c => c.Key, k => new ConvertibleClass(k))
611+
.HasDefaultValue(new ConvertibleClass(1));
612+
613+
await using var tempTable = await SUT.CreateTempTableAsync(ActDbContext.GetEntityType<TempTable<ConvertibleClass>>(), _optionsWithNonUniqueNameAndNoPrimaryKey);
614+
615+
var columns = AssertDbContext.GetTempTableColumns<TempTable<ConvertibleClass>>().ToList();
616+
ValidateColumn(columns[0], nameof(TempTable<ConvertibleClass>.Column1), "INTEGER", false, "1");
617+
}
618+
605619
[Fact]
606620
public async Task Should_create_temp_table_with_string_with_max_length()
607621
{
@@ -714,12 +728,13 @@ public async Task Should_create_temp_table_for_entity_with_many_owned_types()
714728
ValidateColumn(columns[3], nameof(OwnedEntity.StringColumn), "TEXT", true);
715729
}
716730

717-
private static void ValidateColumn(SqliteTableInfo column, string name, string type, bool isNullable)
731+
private static void ValidateColumn(SqliteTableInfo column, string name, string type, bool isNullable, string? defaultValue = null)
718732
{
719733
ArgumentNullException.ThrowIfNull(column);
720734

721735
column.Name.Should().Be(name);
722736
column.Type.Should().Be(type);
723737
column.NotNull.Should().Be(isNullable ? 0 : 1);
738+
column.Dflt_Value.Should().Be(defaultValue);
724739
}
725740
}

tests/Thinktecture.EntityFrameworkCore.Sqlite.Tests/TestDatabaseContext/SqliteTableInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ public class SqliteTableInfo
99
public string? Name { get; set; }
1010
public string? Type { get; set; }
1111
public long? NotNull { get; set; }
12-
public byte[]? Dflt_Value { get; set; }
12+
public string? Dflt_Value { get; set; }
1313
public long? PK { get; set; }
14-
}
14+
}

0 commit comments

Comments
 (0)