Skip to content

Commit 794e31c

Browse files
committed
SQLite Scaffolding: Use column type and values to provide a better CLR type
Here's a table highlighting some of the improvements. Column type | Sample value | Before | After ----------- | -------------------------------------- | ------ | ----- BOOLEAN | 0 | byte[] | bool SMALLINT | 0 | long | short INT | 0 | long | int BIGINT | 0 | long | long TEXT | '0.0' | string | decimal TEXT | '1970-01-01' | string | DateOnly TEXT | '1970-01-01 00:00:00' | string | DateTime TEXT | '00:00:00' | string | TimeSpan TEXT | '00000000-0000-0000-0000-000000000000' | string | Guid STRING | 'ABC' | byte[] | string Resolves #8824
1 parent c63634b commit 794e31c

File tree

13 files changed

+901
-11
lines changed

13 files changed

+901
-11
lines changed

src/EFCore.Design/Metadata/Internal/ScaffoldingAnnotationNames.cs

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ public static class ScaffoldingAnnotationNames
4343
/// </summary>
4444
public const string ConcurrencyToken = "ConcurrencyToken";
4545

46+
/// <summary>
47+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
48+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
49+
/// any release. You should only use it directly in your code with extreme caution and knowing that
50+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
51+
/// </summary>
52+
public const string ClrType = "ClrType";
53+
4654
/// <summary>
4755
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
4856
/// the same compatibility standards as public APIs. It may be changed or removed without notice in

src/EFCore.Design/Scaffolding/Internal/IScaffoldingTypeMapper.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ public interface IScaffoldingTypeMapper
1717
/// any release. You should only use it directly in your code with extreme caution and knowing that
1818
/// doing so can result in application failures when updating to a new Entity Framework Core release.
1919
/// </summary>
20-
TypeScaffoldingInfo? FindMapping(string storeType, bool keyOrIndex, bool rowVersion);
20+
TypeScaffoldingInfo? FindMapping(string storeType, bool keyOrIndex, bool rowVersion, Type? clrType = null);
2121
}

src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,8 @@ protected virtual EntityTypeBuilder VisitColumns(EntityTypeBuilder builder, ICol
487487

488488
property.Metadata.AddAnnotations(
489489
column.GetAnnotations().Where(
490-
a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken));
490+
a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken
491+
&& a.Name != ScaffoldingAnnotationNames.ClrType));
491492

492493
return property;
493494
}
@@ -967,7 +968,8 @@ protected virtual List<string> ExistingIdentifiers(IReadOnlyEntityType entityTyp
967968
return _scaffoldingTypeMapper.FindMapping(
968969
column.StoreType,
969970
column.IsKeyOrIndex(),
970-
column.IsRowVersion());
971+
column.IsRowVersion(),
972+
(Type?)column[ScaffoldingAnnotationNames.ClrType]);
971973
}
972974

973975
private static void AssignOnDeleteAction(

src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ public ScaffoldingTypeMapper(IRelationalTypeMappingSource typeMappingSource)
3333
public virtual TypeScaffoldingInfo? FindMapping(
3434
string storeType,
3535
bool keyOrIndex,
36-
bool rowVersion)
36+
bool rowVersion,
37+
Type? clrType = null)
3738
{
38-
var mapping = _typeMappingSource.FindMapping(storeType);
39+
var mapping = clrType is null
40+
? _typeMappingSource.FindMapping(storeType)
41+
: _typeMappingSource.FindMapping(clrType, storeType);
3942
if (mapping == null)
4043
{
4144
return null;

src/EFCore.Sqlite.Core/Diagnostics/Internal/SqliteLoggingDefinitions.cs

+24
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,28 @@ public class SqliteLoggingDefinitions : RelationalLoggingDefinitions
130130
/// doing so can result in application failures when updating to a new Entity Framework Core release.
131131
/// </summary>
132132
public EventDefinitionBase? LogCompositeKeyWithValueGeneration;
133+
134+
/// <summary>
135+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
136+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
137+
/// any release. You should only use it directly in your code with extreme caution and knowing that
138+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
139+
/// </summary>
140+
public EventDefinitionBase? LogInferringTypes;
141+
142+
/// <summary>
143+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
144+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
145+
/// any release. You should only use it directly in your code with extreme caution and knowing that
146+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
147+
/// </summary>
148+
public EventDefinitionBase? LogOutOfRangeWarning;
149+
150+
/// <summary>
151+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
152+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
153+
/// any release. You should only use it directly in your code with extreme caution and knowing that
154+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
155+
/// </summary>
156+
public EventDefinitionBase? LogFormatWarning;
133157
}

src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs

+28-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ private enum Id
4747
PrimaryKeyFound,
4848
SchemasNotSupportedWarning,
4949
TableFound,
50-
UniqueConstraintFound
50+
UniqueConstraintFound,
51+
InferringTypes,
52+
OutOfRangeWarning,
53+
FormatWarning
5154
}
5255

5356
private static readonly string ValidationPrefix = DbLoggerCategory.Model.Validation.Name + ".";
@@ -213,4 +216,28 @@ private static EventId MakeScaffoldingId(Id id)
213216
/// This event is in the <see cref="DbLoggerCategory.Scaffolding" /> category.
214217
/// </remarks>
215218
public static readonly EventId UniqueConstraintFound = MakeScaffoldingId(Id.UniqueConstraintFound);
219+
220+
/// <summary>
221+
/// Inferring CLR types.
222+
/// </summary>
223+
/// <remarks>
224+
/// This event is in the <see cref="DbLoggerCategory.Scaffolding" /> category.
225+
/// </remarks>
226+
public static readonly EventId InferringTypes = MakeScaffoldingId(Id.InferringTypes);
227+
228+
/// <summary>
229+
/// Values are out of range for the type.
230+
/// </summary>
231+
/// <remarks>
232+
/// This event is in the <see cref="DbLoggerCategory.Scaffolding" /> category.
233+
/// </remarks>
234+
public static readonly EventId OutOfRangeWarning = MakeScaffoldingId(Id.OutOfRangeWarning);
235+
236+
/// <summary>
237+
/// Values are in an invalid format for the type.
238+
/// </summary>
239+
/// <remarks>
240+
/// This event is in the <see cref="DbLoggerCategory.Scaffolding" /> category.
241+
/// </remarks>
242+
public static readonly EventId FormatWarning = MakeScaffoldingId(Id.FormatWarning);
216243
}

src/EFCore.Sqlite.Core/Extensions/Internal/SqliteLoggerExtensions.cs

+64
Original file line numberDiff line numberDiff line change
@@ -413,4 +413,68 @@ private static string CompositeKeyWithValueGeneration(EventDefinitionBase defini
413413
p.Key.DeclaringEntityType.DisplayName(),
414414
p.Key.Properties.Format());
415415
}
416+
417+
/// <summary>
418+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
419+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
420+
/// any release. You should only use it directly in your code with extreme caution and knowing that
421+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
422+
/// </summary>
423+
public static void InferringTypes(
424+
this IDiagnosticsLogger<DbLoggerCategory.Scaffolding> diagnostics,
425+
string? tableName)
426+
{
427+
var definition = SqliteResources.LogInferringTypes(diagnostics);
428+
429+
if (diagnostics.ShouldLog(definition))
430+
{
431+
definition.Log(diagnostics, tableName);
432+
}
433+
434+
// No DiagnosticsSource events because these are purely design-time messages
435+
}
436+
437+
/// <summary>
438+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
439+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
440+
/// any release. You should only use it directly in your code with extreme caution and knowing that
441+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
442+
/// </summary>
443+
public static void OutOfRangeWarning(
444+
this IDiagnosticsLogger<DbLoggerCategory.Scaffolding> diagnostics,
445+
string? columnName,
446+
string? tableName,
447+
string? type)
448+
{
449+
var definition = SqliteResources.LogOutOfRangeWarning(diagnostics);
450+
451+
if (diagnostics.ShouldLog(definition))
452+
{
453+
definition.Log(diagnostics, columnName, tableName, type);
454+
}
455+
456+
// No DiagnosticsSource events because these are purely design-time messages
457+
}
458+
459+
/// <summary>
460+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
461+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
462+
/// any release. You should only use it directly in your code with extreme caution and knowing that
463+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
464+
/// </summary>
465+
public static void FormatWarning(
466+
this IDiagnosticsLogger<DbLoggerCategory.Scaffolding> diagnostics,
467+
string? columnName,
468+
string? tableName,
469+
string? type)
470+
{
471+
var definition = SqliteResources.LogFormatWarning(diagnostics);
472+
473+
if (diagnostics.ShouldLog(definition))
474+
{
475+
definition.Log(diagnostics, columnName, tableName, type);
476+
}
477+
478+
// No DiagnosticsSource events because these are purely design-time messages
479+
}
416480
}

src/EFCore.Sqlite.Core/Properties/SqliteStrings.Designer.cs

+75
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/EFCore.Sqlite.Core/Properties/SqliteStrings.resx

+12
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@
143143
<value>Skipping foreign key with identity '{id}' on table '{tableName}' since principal table '{principalTableName}' was not found in the model. This usually happens when the principal table was not included in the selection set.</value>
144144
<comment>Warning SqliteEventId.ForeignKeyReferencesMissingTableWarning string? string? string?</comment>
145145
</data>
146+
<data name="LogFormatWarning" xml:space="preserve">
147+
<value>The column '{columnName}' on table '{tableName}' should map to a property of type '{type}', but its values are in an incompatible format. Using a different type.</value>
148+
<comment>Warning SqliteEventId.FormatWarning string? string? string?</comment>
149+
</data>
146150
<data name="LogFoundColumn" xml:space="preserve">
147151
<value>Found column on table '{tableName}' with name: '{columnName}', data type: {dataType}, not nullable: {notNullable}, default value: {defaultValue}.</value>
148152
<comment>Debug SqliteEventId.ColumnFound string? string? string? bool string?</comment>
@@ -167,10 +171,18 @@
167171
<value>Found unique constraint on table '{tableName}' with name: {uniqueConstraintName}.</value>
168172
<comment>Debug SqliteEventId.UniqueConstraintFound string? string?</comment>
169173
</data>
174+
<data name="LogInferringTypes" xml:space="preserve">
175+
<value>Querying table '{tableName}' to determine an appropriate CLR type for each column.</value>
176+
<comment>Debug SqliteEventId.InferringTypes string?</comment>
177+
</data>
170178
<data name="LogMissingTable" xml:space="preserve">
171179
<value>Unable to find a table in the database matching the selected table '{table}'.</value>
172180
<comment>Warning SqliteEventId.MissingTableWarning string?</comment>
173181
</data>
182+
<data name="LogOutOfRangeWarning" xml:space="preserve">
183+
<value>The column '{columnName}' on table '{tableName}' should map to a property of type '{type}', but its values are out of range. Using a different type.</value>
184+
<comment>Warning SqliteEventId.OutOfRangeWarning string? string? string?</comment>
185+
</data>
174186
<data name="LogPrincipalColumnNotFound" xml:space="preserve">
175187
<value>Skipping foreign key with identity '{id}' on table '{tableName}', since the principal column '{principalColumnName}' on the foreign key's principal table, '{principalTableName}', was not found in the model.</value>
176188
<comment>Warning SqliteEventId.ForeignKeyPrincipalColumnMissingWarning string? string? string? string?</comment>

0 commit comments

Comments
 (0)