Skip to content

Commit

Permalink
Updates to relational type mapping
Browse files Browse the repository at this point in the history
These changes address issue #4425 while at the same time re-introducing the parsing of sizes in store type names such that these can then be used in parameters for #4134.

The mapping of strings and binary types based on facets has been split out such that the information provided by the type mapper can be interpreted more easily by the scaffolding code. This also simplifies the type mapper APIs themselves. A new class ScaffoldingTypeMapper has been introduced that can be used to determine what needs to be scaffolded for a given store type. This has not yet been integrated into scaffolding, but has unit tests to check it gives the correct answers. Scaffolding must provide this service with the full store type name (e.g. nvarchar(256)" together with information about whether the property will be a key or index or a rowversion. The service then gives back data indicating whether the type is inferred (need not be explicitly set) and, if so, whether max length and/or unicode factes needs to be set.
  • Loading branch information
ajcvickers committed May 18, 2016
1 parent c6e0f04 commit 22b57df
Show file tree
Hide file tree
Showing 35 changed files with 1,338 additions and 415 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@
</Compile>
<Compile Include="Properties\InternalsVisibleTo.cs" />
<Compile Include="RelationalScaffoldingModelFactory.cs" />
<Compile Include="ScaffoldingTypeMapper.cs" />
<Compile Include="TableSelectionSet.cs" />
<Compile Include="TypeScaffoldingInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\RelationalDesignStrings.resx">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ protected virtual PropertyBuilder VisitColumn([NotNull] EntityTypeBuilder builde

var property = builder.Property(clrType, GetPropertyName(column));

if (TypeMapper.GetMapping(property.Metadata).DefaultTypeName != column.DataType
if (TypeMapper.GetMapping(property.Metadata).StoreType != column.DataType
&& !string.IsNullOrWhiteSpace(column.DataType))
{
property.HasColumnType(column.DataType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Scaffolding
{
public class ScaffoldingTypeMapper
{
public ScaffoldingTypeMapper([NotNull] IRelationalTypeMapper typeMapper)
{
Check.NotNull(typeMapper, nameof(typeMapper));

TypeMapper = typeMapper;
}

protected virtual IRelationalTypeMapper TypeMapper { get; }

public virtual TypeScaffoldingInfo FindMapping(
[NotNull] string storeType,
bool keyOrIndex,
bool rowVersion)
{
Check.NotEmpty(storeType, nameof(storeType));

var mapping = TypeMapper.FindMapping(storeType);
if (mapping == null)
{
return null;
}

if (mapping.ClrType == typeof(byte[])
&& TypeMapper.ByteArrayMapper != null)
{
var byteArrayMapping = TypeMapper.ByteArrayMapper.FindMapping(rowVersion, keyOrIndex, mapping.Size);

if (byteArrayMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
{
return new TypeScaffoldingInfo(
mapping.ClrType,
inferred: true,
scaffoldUnicode: null,
scaffoldMaxLength: byteArrayMapping.HasNonDefaultSize ? byteArrayMapping.Size : null);
}
}
else if (mapping.ClrType == typeof(string)
&& TypeMapper.StringMapper != null)
{
var stringMapping = TypeMapper.StringMapper.FindMapping(mapping.IsUnicode, keyOrIndex, mapping.Size);

if (stringMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
{
return new TypeScaffoldingInfo(
mapping.ClrType,
inferred: true,
scaffoldUnicode: stringMapping.HasNonDefaultUnicode ? (bool?)stringMapping.IsUnicode : null,
scaffoldMaxLength: stringMapping.HasNonDefaultSize ? stringMapping.Size : null);
}
}
else
{
var defaultMapping = TypeMapper.GetMapping(mapping.ClrType);

if (defaultMapping.StoreType.Equals(storeType, StringComparison.OrdinalIgnoreCase))
{
return new TypeScaffoldingInfo(
mapping.ClrType,
inferred: true,
scaffoldUnicode: null,
scaffoldMaxLength: null);
}
}

return new TypeScaffoldingInfo(
mapping.ClrType,
inferred: false,
scaffoldUnicode: null,
scaffoldMaxLength: null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Scaffolding
{
public class TypeScaffoldingInfo
{
public TypeScaffoldingInfo([NotNull] Type clrType, bool inferred, bool? scaffoldUnicode, int? scaffoldMaxLength)
{
Check.NotNull(clrType, nameof(clrType));

IsInferred = inferred;
ScaffoldUnicode = scaffoldUnicode;
ScaffoldMaxLength = scaffoldMaxLength;
ClrType = clrType;
}

public virtual Type ClrType { get; }
public virtual bool IsInferred { get; }
public virtual bool? ScaffoldUnicode { get; }
public virtual int? ScaffoldMaxLength { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ protected virtual void EnsureSharedColumnsCompatibility([NotNull] IModel model)
{
var previousAnnotations = RelationalExtensions.For(duplicateProperty);
var currentTypeString = propertyAnnotations.ColumnType
?? TypeMapper.GetMapping(property).DefaultTypeName;
?? TypeMapper.GetMapping(property).StoreType;
var previousTypeString = previousAnnotations.ColumnType
?? TypeMapper.GetMapping(duplicateProperty).DefaultTypeName;
?? TypeMapper.GetMapping(duplicateProperty).StoreType;
if (!currentTypeString.Equals(previousTypeString, StringComparison.OrdinalIgnoreCase))
{
ShowError(RelationalStrings.DuplicateColumnName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,9 @@
<Compile Include="RelationalQueryableExtensions.cs" />
<Compile Include="RelationalReferenceCollectionBuilderExtensions.cs" />
<Compile Include="RelationalReferenceReferenceBuilderExtensions.cs" />
<Compile Include="Storage\ByteArrayRelationalTypeMapper.cs" />
<Compile Include="Storage\DbContextTransactionExtensions.cs" />
<Compile Include="Storage\IByteArrayRelationalTypeMapper.cs" />
<Compile Include="Storage\Internal\CompositeRelationalParameter.cs" />
<Compile Include="Storage\Internal\DynamicRelationalParameter.cs" />
<Compile Include="Storage\Internal\RawSqlCommandBuilder.cs" />
Expand Down Expand Up @@ -330,6 +332,7 @@
<Compile Include="Storage\IRelationalValueBufferFactory.cs" />
<Compile Include="Storage\IRelationalValueBufferFactoryFactory.cs" />
<Compile Include="Storage\ISqlGenerationHelper.cs" />
<Compile Include="Storage\IStringRelationalTypeMapper.cs" />
<Compile Include="Storage\ParameterNameGenerator.cs" />
<Compile Include="Storage\ParameterNameGeneratorFactory.cs" />
<Compile Include="Storage\RawSqlCommand.cs" />
Expand All @@ -339,12 +342,12 @@
<Compile Include="Storage\RelationalDatabaseCreator.cs" />
<Compile Include="Storage\RelationalDatabaseProviderServices.cs" />
<Compile Include="Storage\RelationalDataReader.cs" />
<Compile Include="Storage\RelationalSizedTypeMapping.cs" />
<Compile Include="Storage\RelationalSqlGenerationHelper.cs" />
<Compile Include="Storage\RelationalTransaction.cs" />
<Compile Include="Storage\RelationalTypeMapper.cs" />
<Compile Include="Storage\RelationalTypeMapperExtensions.cs" />
<Compile Include="Storage\RelationalTypeMapping.cs" />
<Compile Include="Storage\StringRelationalTypeMapper.cs" />
<Compile Include="Storage\TypedRelationalValueBufferFactoryFactory.cs" />
<Compile Include="Storage\UntypedRelationalValueBufferFactoryFactory.cs" />
<Compile Include="Update\AffectedCountModificationCommandBatch.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,9 @@ protected virtual IEnumerable<MigrationOperation> Diff([NotNull] IProperty sourc
}

var sourceColumnType = sourceAnnotations.ColumnType
?? TypeMapper.GetMapping(source).DefaultTypeName;
?? TypeMapper.GetMapping(source).StoreType;
var targetColumnType = targetAnnotations.ColumnType
?? TypeMapper.GetMapping(target).DefaultTypeName;
?? TypeMapper.GetMapping(target).StoreType;

var targetMigrationsAnnotations = MigrationsAnnotations.For(target).ToList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ protected virtual void Generate(
{
builder
.Append(" AS ")
.Append(TypeMapper.GetMapping(operation.ClrType).DefaultTypeName);
.Append(TypeMapper.GetMapping(operation.ClrType).StoreType);
}

builder
Expand Down Expand Up @@ -614,8 +614,8 @@ protected virtual void ColumnDefinition(
{
var property = FindProperty(model, schema, table, name);
type = property != null
? TypeMapper.GetMapping(property).DefaultTypeName
: TypeMapper.GetMapping(clrType).DefaultTypeName;
? TypeMapper.GetMapping(property).StoreType
: TypeMapper.GetMapping(clrType).StoreType;
}

builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ public virtual Expression VisitExplicitCast(ExplicitCastExpression explicitCastE
throw new InvalidOperationException(RelationalStrings.UnsupportedType(explicitCastExpression.Type.Name));
}

_relationalCommandBuilder.Append(typeMapping.DefaultTypeName);
_relationalCommandBuilder.Append(typeMapping.StoreType);

_relationalCommandBuilder.Append(")");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Concurrent;
using JetBrains.Annotations;

namespace Microsoft.EntityFrameworkCore.Storage
{
public class ByteArrayRelationalTypeMapper : IByteArrayRelationalTypeMapper
{
private readonly ConcurrentDictionary<int, RelationalTypeMapping> _boundedMappings
= new ConcurrentDictionary<int, RelationalTypeMapping>();

public ByteArrayRelationalTypeMapper(
int maxBoundedLength,
[NotNull] RelationalTypeMapping defaultMapping,
[CanBeNull] RelationalTypeMapping unboundedMapping,
[CanBeNull] RelationalTypeMapping keyMapping,
[CanBeNull] RelationalTypeMapping rowVersionMapping,
[NotNull] Func<int, RelationalTypeMapping> createBoundedMapping)
{
MaxBoundedLength = maxBoundedLength;
DefaultMapping = defaultMapping;
UnboundedMapping = unboundedMapping;
KeyMapping = keyMapping;
RowVersionMapping = rowVersionMapping;
CreateBoundedMapping = createBoundedMapping;
}

public virtual int MaxBoundedLength { get; }
public virtual RelationalTypeMapping DefaultMapping { get; }
public virtual RelationalTypeMapping UnboundedMapping { get; }
public virtual RelationalTypeMapping KeyMapping { get; }
public virtual RelationalTypeMapping RowVersionMapping { get; }
public virtual Func<int, RelationalTypeMapping> CreateBoundedMapping { get; }

public virtual RelationalTypeMapping FindMapping(bool rowVersion, bool keyOrIndex, int? size)
{
if (rowVersion
&& RowVersionMapping != null)
{
return RowVersionMapping;
}

var defaultMapping = keyOrIndex && KeyMapping != null ? KeyMapping : DefaultMapping;

if (size.HasValue
&& size != defaultMapping.Size)
{
return size <= MaxBoundedLength
? _boundedMappings.GetOrAdd(size.Value, CreateBoundedMapping)
: UnboundedMapping;
}

return defaultMapping;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.EntityFrameworkCore.Storage
{
public interface IByteArrayRelationalTypeMapper
{
RelationalTypeMapping FindMapping(bool rowVersion, bool keyOrIndex, int? size);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public interface IRelationalTypeMapper
RelationalTypeMapping FindMapping([NotNull] IProperty property);
RelationalTypeMapping FindMapping([NotNull] Type clrType);

RelationalTypeMapping FindMapping([NotNull] string typeName);
void ValidateTypeName([NotNull] string typeName);
RelationalTypeMapping FindMapping([NotNull] string storeType);
void ValidateTypeName([NotNull] string storeType);

IByteArrayRelationalTypeMapper ByteArrayMapper { get; }
IStringRelationalTypeMapper StringMapper { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.EntityFrameworkCore.Storage
{
public interface IStringRelationalTypeMapper
{
RelationalTypeMapping FindMapping(bool unicode, bool keyOrIndex, int? maxLength);
}
}

This file was deleted.

Loading

0 comments on commit 22b57df

Please sign in to comment.