Skip to content

Commit

Permalink
Fix for 11614 - Adding HasPrecision() APIs (#20468)
Browse files Browse the repository at this point in the history
Fixes #11614  - HasPrecision(). Updates to scaffolding and migrations.
Now process all facets for all TypeMappings in Scaffolding.
Update format of datetime parameters to include the fractional seconds and update tests to match
  • Loading branch information
lajones committed Mar 31, 2020
1 parent 5fff1f6 commit 7b48952
Show file tree
Hide file tree
Showing 49 changed files with 1,167 additions and 279 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ protected virtual void Generate([NotNull] AddColumnOperation operation, [NotNull
.Append(Code.Literal(operation.MaxLength.Value));
}

if (operation.Precision.HasValue)
{
builder.AppendLine(",")
.Append("precision: ")
.Append(Code.Literal(operation.Precision.Value));
}

if (operation.Scale.HasValue)
{
builder.AppendLine(",")
.Append("scale: ")
.Append(Code.Literal(operation.Scale.Value));
}

if (operation.IsRowVersion)
{
builder
Expand Down Expand Up @@ -492,6 +506,20 @@ protected virtual void Generate([NotNull] AlterColumnOperation operation, [NotNu
.Append(Code.Literal(operation.MaxLength.Value));
}

if (operation.Precision.HasValue)
{
builder.AppendLine(",")
.Append("precision: ")
.Append(Code.Literal(operation.Precision.Value));
}

if (operation.Scale.HasValue)
{
builder.AppendLine(",")
.Append("scale: ")
.Append(Code.Literal(operation.Scale.Value));
}

if (operation.IsRowVersion)
{
builder
Expand Down Expand Up @@ -569,6 +597,20 @@ protected virtual void Generate([NotNull] AlterColumnOperation operation, [NotNu
.Append(Code.Literal(operation.OldColumn.MaxLength.Value));
}

if (operation.OldColumn.Precision.HasValue)
{
builder.AppendLine(",")
.Append("oldPrecision: ")
.Append(Code.Literal(operation.OldColumn.Precision.Value));
}

if (operation.OldColumn.Scale.HasValue)
{
builder.AppendLine(",")
.Append("oldScale: ")
.Append(Code.Literal(operation.OldColumn.Scale.Value));
}

if (operation.OldColumn.IsRowVersion)
{
builder
Expand Down Expand Up @@ -1033,6 +1075,22 @@ protected virtual void Generate([NotNull] CreateTableOperation operation, [NotNu
.Append(", ");
}

if (column.Precision.HasValue)
{
builder
.Append("precision: ")
.Append(Code.Literal(column.Precision.Value))
.Append(", ");
}

if (column.Scale.HasValue)
{
builder
.Append("scale: ")
.Append(Code.Literal(column.Scale.Value))
.Append(", ");
}

if (column.IsRowVersion)
{
builder.Append("rowVersion: true, ");
Expand Down
48 changes: 48 additions & 0 deletions src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,10 @@ protected virtual void GeneratePropertyAnnotations([NotNull] IProperty property,
nameof(PropertyBuilder.HasMaxLength),
stringBuilder);

GenerateFluentApiForPrecisionAndScale(
ref annotations,
stringBuilder);

GenerateFluentApiForAnnotation(
ref annotations,
CoreAnnotationNames.Unicode,
Expand Down Expand Up @@ -1300,6 +1304,50 @@ protected virtual void GenerateFluentApiForAnnotation(
}
}

/// <summary>
/// Generates a Fluent API call for the Precision and Scale annotations.
/// </summary>
/// <param name="annotations"> The list of annotations. </param>
/// <param name="stringBuilder"> The builder code is added to. </param>
protected virtual void GenerateFluentApiForPrecisionAndScale(
[NotNull] ref List<IAnnotation> annotations,
[NotNull] IndentedStringBuilder stringBuilder)
{
var precisionAnnotation = annotations
.FirstOrDefault(a => a.Name == CoreAnnotationNames.Precision);
var precisionValue = precisionAnnotation?.Value;

if (precisionValue != null)
{
stringBuilder
.AppendLine()
.Append(".")
.Append(nameof(PropertyBuilder.HasPrecision))
.Append("(")
.Append(Code.UnknownLiteral(precisionValue));

var scaleAnnotation = annotations
.FirstOrDefault(a => a.Name == CoreAnnotationNames.Scale);
var scaleValue = (int?)scaleAnnotation?.Value;

if (scaleValue != null)
{
if (scaleValue != 0)
{
stringBuilder
.Append(", ")
.Append(Code.UnknownLiteral(scaleValue));
}

annotations.Remove(scaleAnnotation);
}

stringBuilder.Append(")");

annotations.Remove(precisionAnnotation);
}
}

/// <summary>
/// Generates code for an annotation.
/// </summary>
Expand Down
17 changes: 17 additions & 0 deletions src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,8 @@ private void GenerateProperty(IProperty property, bool useDataAnnotations)
var annotations = property.GetAnnotations().ToList();

RemoveAnnotation(ref annotations, CoreAnnotationNames.MaxLength);
RemoveAnnotation(ref annotations, CoreAnnotationNames.Precision);
RemoveAnnotation(ref annotations, CoreAnnotationNames.Scale);
RemoveAnnotation(ref annotations, CoreAnnotationNames.TypeMapping);
RemoveAnnotation(ref annotations, CoreAnnotationNames.Unicode);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.ColumnName);
Expand Down Expand Up @@ -695,6 +697,21 @@ private void GenerateProperty(IProperty property, bool useDataAnnotations)
}
}

var precision = property.GetPrecision();
var scale = property.GetScale();
if (precision != null && scale != null && scale != 0)
{
lines.Add(
$".{nameof(PropertyBuilder.HasPrecision)}" +
$"({_code.Literal(precision.Value)}, {_code.Literal(scale.Value)})");
}
else if (precision != null)
{
lines.Add(
$".{nameof(PropertyBuilder.HasPrecision)}" +
$"({_code.Literal(precision.Value)})");
}

if (property.IsUnicode() != null)
{
lines.Add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,20 @@ protected virtual PropertyBuilder VisitColumn([NotNull] EntityTypeBuilder builde
property.HasMaxLength(typeScaffoldingInfo.ScaffoldMaxLength.Value);
}

if (typeScaffoldingInfo.ScaffoldPrecision.HasValue)
{
if (typeScaffoldingInfo.ScaffoldScale.HasValue)
{
property.HasPrecision(
typeScaffoldingInfo.ScaffoldPrecision.Value,
typeScaffoldingInfo.ScaffoldScale.Value);
}
else
{
property.HasPrecision(typeScaffoldingInfo.ScaffoldPrecision.Value);
}
}

if (column.ValueGenerated == ValueGenerated.OnAdd)
{
property.ValueGeneratedOnAdd();
Expand Down
174 changes: 85 additions & 89 deletions src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,112 +57,108 @@ public ScaffoldingTypeMapper([NotNull] IRelationalTypeMappingSource typeMappingS
bool? scaffoldUnicode = null;
bool? scaffoldFixedLength = null;
int? scaffoldMaxLength = null;

if (mapping.ClrType == typeof(byte[]))
int? scaffoldPrecision = null;
int? scaffoldScale = null;

var unwrappedClrType = mapping.ClrType.UnwrapNullableType();

// Check for inference
var defaultTypeMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: mapping.Size,
rowVersion: rowVersion,
fixedLength: mapping.IsFixedLength,
precision: mapping.Precision,
scale: mapping.Scale);

if (defaultTypeMapping != null
&& string.Equals(defaultTypeMapping.StoreType, storeType, StringComparison.OrdinalIgnoreCase))
{
// Check for inference
var byteArrayMapping = _typeMappingSource.FindMapping(
typeof(byte[]),
canInfer = true;

// Check for Unicode
var unicodeMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: null,
size: mapping.Size,
rowVersion: rowVersion,
fixedLength: mapping.IsFixedLength,
precision: mapping.Precision,
scale: mapping.Scale);

scaffoldUnicode = unicodeMapping.IsUnicode != defaultTypeMapping.IsUnicode ? (bool?)defaultTypeMapping.IsUnicode : null;

// Check for fixed-length
var fixedLengthMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: mapping.Size,
fixedLength: mapping.IsFixedLength);

if (byteArrayMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
{
canInfer = true;

// Check for fixed-length
var fixedLengthMapping = _typeMappingSource.FindMapping(
typeof(byte[]),
null,
keyOrIndex,
rowVersion: rowVersion,
size: mapping.Size,
fixedLength: false);

scaffoldFixedLength = fixedLengthMapping.IsFixedLength != byteArrayMapping.IsFixedLength
? (bool?)byteArrayMapping.IsFixedLength
: null;

// Check for size
var sizedMapping = _typeMappingSource.FindMapping(
typeof(byte[]),
null,
keyOrIndex,
rowVersion: rowVersion,
fixedLength: mapping.IsFixedLength);

scaffoldMaxLength = sizedMapping.Size != byteArrayMapping.Size ? byteArrayMapping.Size : null;
}
}
else if (mapping.ClrType == typeof(string))
{
// Check for inference
var stringMapping = _typeMappingSource.FindMapping(
typeof(string),
fixedLength: null,
precision: mapping.Precision,
scale: mapping.Scale);

scaffoldFixedLength = fixedLengthMapping.IsFixedLength != defaultTypeMapping.IsFixedLength
? (bool?)defaultTypeMapping.IsFixedLength
: null;

// Check for size (= max-length)
var sizedMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: null,
rowVersion: rowVersion,
fixedLength: false, // Fixed length with no size is not valid
precision: mapping.Precision,
scale: mapping.Scale);

scaffoldMaxLength = sizedMapping.Size != defaultTypeMapping.Size ? defaultTypeMapping.Size : null;

// Check for precision
var precisionMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: mapping.Size,
fixedLength: mapping.IsFixedLength);

if (stringMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
{
canInfer = true;

// Check for Unicode
var unicodeMapping = _typeMappingSource.FindMapping(
typeof(string),
null,
keyOrIndex,
unicode: true,
size: mapping.Size,
fixedLength: mapping.IsFixedLength);

scaffoldUnicode = unicodeMapping.IsUnicode != stringMapping.IsUnicode ? (bool?)stringMapping.IsUnicode : null;

// Check for fixed-length
var fixedLengthMapping = _typeMappingSource.FindMapping(
typeof(string),
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: mapping.Size,
fixedLength: false);

scaffoldFixedLength = fixedLengthMapping.IsFixedLength != stringMapping.IsFixedLength
? (bool?)stringMapping.IsFixedLength
: null;

var sizedMapping = _typeMappingSource.FindMapping(
typeof(string),
null,
keyOrIndex,
unicode: mapping.IsUnicode,
fixedLength: false); // Fixed length with no size is not valid

scaffoldMaxLength = sizedMapping.Size != stringMapping.Size ? stringMapping.Size : null;
}
}
else
{
var defaultMapping = _typeMappingSource.FindMapping(mapping.ClrType);
rowVersion: rowVersion,
fixedLength: mapping.IsFixedLength,
precision: null,
scale: mapping.Scale);

scaffoldPrecision = precisionMapping.Precision != defaultTypeMapping.Precision ? defaultTypeMapping.Precision : null;

// Check for scale
var scaleMapping = _typeMappingSource.FindMapping(
unwrappedClrType,
null,
keyOrIndex,
unicode: mapping.IsUnicode,
size: mapping.Size,
rowVersion: rowVersion,
fixedLength: mapping.IsFixedLength,
precision: mapping.Precision,
scale: null);

if (string.Equals(defaultMapping?.StoreType, storeType, StringComparison.OrdinalIgnoreCase)
&& mapping.ClrType.UnwrapNullableType() != typeof(decimal))
{
canInfer = true;
}
scaffoldScale = scaleMapping.Scale != defaultTypeMapping.Scale ? defaultTypeMapping.Scale : null;
}

return new TypeScaffoldingInfo(
mapping.ClrType,
canInfer,
scaffoldUnicode,
scaffoldMaxLength,
scaffoldFixedLength);
scaffoldFixedLength,
scaffoldPrecision,
scaffoldScale);
}
}
}
Loading

0 comments on commit 7b48952

Please sign in to comment.