Skip to content

Commit

Permalink
Add default type mappings for remaining complex types to support comp…
Browse files Browse the repository at this point in the history
…iled models in EF Core 8.
  • Loading branch information
lauxjpn committed Feb 12, 2024
1 parent 9559ca1 commit ee1058b
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ private SqlExpression ApplyPathLocationTypeMapping(SqlExpression expression)
sqlConstantExpression.TypeMapping is MySqlStringTypeMapping stringTypeMapping &&
!stringTypeMapping.IsUnquoted)
{
pathLocation = sqlConstantExpression.ApplyTypeMapping(stringTypeMapping.Clone(true));
pathLocation = sqlConstantExpression.ApplyTypeMapping(stringTypeMapping.Clone(unquoted: true));
}

return pathLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Pomelo.EntityFrameworkCore.MySql.Json.Microsoft.Storage.Internal
{
public class MySqlJsonMicrosoftTypeMapping<T> : MySqlJsonTypeMapping<T>
{
public static new MySqlJsonMicrosoftTypeMapping<T> Default { get; } = new("json", null, null, false, true);

// Called via reflection.
// ReSharper disable once UnusedMember.Global
public MySqlJsonMicrosoftTypeMapping(
Expand Down Expand Up @@ -48,6 +50,13 @@ protected MySqlJsonMicrosoftTypeMapping(
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new MySqlJsonMicrosoftTypeMapping<T>(parameters, MySqlDbType, NoBackslashEscapes, ReplaceLineBreaksWithCharFunction);

protected override RelationalTypeMapping Clone(bool? noBackslashEscapes = null, bool? replaceLineBreaksWithCharFunction = null)
=> new MySqlJsonMicrosoftTypeMapping<T>(
Parameters,
MySqlDbType,
noBackslashEscapes ?? NoBackslashEscapes,
replaceLineBreaksWithCharFunction ?? ReplaceLineBreaksWithCharFunction);

public override Expression GenerateCodeLiteral(object value)
=> value switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private SqlExpression ApplyPathLocationTypeMapping(SqlExpression expression)
sqlConstantExpression.TypeMapping is MySqlStringTypeMapping stringTypeMapping &&
!stringTypeMapping.IsUnquoted)
{
pathLocation = sqlConstantExpression.ApplyTypeMapping(stringTypeMapping.Clone(true));
pathLocation = sqlConstantExpression.ApplyTypeMapping(stringTypeMapping.Clone(unquoted: true));
}

return pathLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace Pomelo.EntityFrameworkCore.MySql.Json.Newtonsoft.Storage.Internal
{
public class MySqlJsonNewtonsoftTypeMapping<T> : MySqlJsonTypeMapping<T>
{
public static new MySqlJsonNewtonsoftTypeMapping<T> Default { get; } = new("json", null, null, false, true);

// Called via reflection.
// ReSharper disable once UnusedMember.Global
public MySqlJsonNewtonsoftTypeMapping(
Expand Down Expand Up @@ -45,6 +47,13 @@ protected MySqlJsonNewtonsoftTypeMapping(
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new MySqlJsonNewtonsoftTypeMapping<T>(parameters, MySqlDbType, NoBackslashEscapes, ReplaceLineBreaksWithCharFunction);

protected override RelationalTypeMapping Clone(bool? noBackslashEscapes = null, bool? replaceLineBreaksWithCharFunction = null)
=> new MySqlJsonNewtonsoftTypeMapping<T>(
Parameters,
MySqlDbType,
noBackslashEscapes ?? NoBackslashEscapes,
replaceLineBreaksWithCharFunction ?? ReplaceLineBreaksWithCharFunction);

public override Expression GenerateCodeLiteral(object value)
=> value switch
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Pomelo Foundation. All rights reserved.
// Licensed under the MIT. See LICENSE in the project root for license information.

using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Pomelo.EntityFrameworkCore.MySql.Storage.Internal;

namespace Pomelo.EntityFrameworkCore.MySql.Design.Internal;

public class MySqlCSharpRuntimeAnnotationCodeGenerator : RelationalCSharpRuntimeAnnotationCodeGenerator
{
public MySqlCSharpRuntimeAnnotationCodeGenerator(
CSharpRuntimeAnnotationCodeGeneratorDependencies dependencies,
RelationalCSharpRuntimeAnnotationCodeGeneratorDependencies relationalDependencies)
: base(dependencies, relationalDependencies)
{
}

public override bool Create(
CoreTypeMapping typeMapping,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters,
ValueComparer valueComparer = null,
ValueComparer keyValueComparer = null,
ValueComparer providerValueComparer = null)
{
var result = base.Create(typeMapping, parameters, valueComparer, keyValueComparer, providerValueComparer);

if (typeMapping is IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator extension)
{
extension.Create(
CreateDefaultTypeMapping(typeMapping, parameters),
parameters);
}

return result;
}
}
2 changes: 2 additions & 0 deletions src/EFCore.MySql/Design/Internal/MySqlDesignTimeServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Pomelo.EntityFrameworkCore.MySql.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.Extensions.DependencyInjection;

Expand All @@ -14,6 +15,7 @@ public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollec
{
serviceCollection.AddEntityFrameworkMySql();
new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)
.TryAdd<ICSharpRuntimeAnnotationCodeGenerator, MySqlCSharpRuntimeAnnotationCodeGenerator>()
.TryAdd<IAnnotationCodeGenerator, MySqlAnnotationCodeGenerator>()
.TryAdd<IDatabaseModelFactory, MySqlDatabaseModelFactory>()
.TryAdd<IProviderConfigurationCodeGenerator, MySqlCodeGenerator>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public MySqlJsonPocoTranslator(
{
_typeMappingSource = typeMappingSource;
_sqlExpressionFactory = sqlExpressionFactory;
_unquotedStringTypeMapping = ((MySqlStringTypeMapping)_typeMappingSource.FindMapping(typeof(string))).Clone(true);
_unquotedStringTypeMapping = ((MySqlStringTypeMapping)_typeMappingSource.FindMapping(typeof(string))).Clone(unquoted: true);
_intTypeMapping = _typeMappingSource.FindMapping(typeof(int));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Pomelo Foundation. All rights reserved.
// Licensed under the MIT. See LICENSE in the project root for license information.

using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Storage;

namespace Pomelo.EntityFrameworkCore.MySql.Storage.Internal;

public interface IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator
{
void Create(
CoreTypeMapping defaultTypeMapping,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters);
}
68 changes: 67 additions & 1 deletion src/EFCore.MySql/Storage/Internal/MySqlJsonTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
// Licensed under the MIT. See LICENSE in the project root for license information.

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MySqlConnector;
Expand All @@ -14,6 +17,8 @@ namespace Pomelo.EntityFrameworkCore.MySql.Storage.Internal
{
public class MySqlJsonTypeMapping<T> : MySqlJsonTypeMapping
{
public static new MySqlJsonTypeMapping<T> Default { get; } = new("json", null, null, false, true);

public MySqlJsonTypeMapping(
[NotNull] string storeType,
[CanBeNull] ValueConverter valueConverter,
Expand Down Expand Up @@ -41,9 +46,16 @@ protected MySqlJsonTypeMapping(

protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new MySqlJsonTypeMapping<T>(parameters, MySqlDbType, NoBackslashEscapes, ReplaceLineBreaksWithCharFunction);

protected override RelationalTypeMapping Clone(bool? noBackslashEscapes = null, bool? replaceLineBreaksWithCharFunction = null)
=> new MySqlJsonTypeMapping<T>(
Parameters,
MySqlDbType,
noBackslashEscapes ?? NoBackslashEscapes,
replaceLineBreaksWithCharFunction ?? ReplaceLineBreaksWithCharFunction);
}

public abstract class MySqlJsonTypeMapping : MySqlStringTypeMapping
public abstract class MySqlJsonTypeMapping : MySqlStringTypeMapping, IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator
{
public MySqlJsonTypeMapping(
[NotNull] string storeType,
Expand Down Expand Up @@ -87,6 +99,13 @@ protected MySqlJsonTypeMapping(
{
}

/// <summary>
/// Supports compiled models via IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator.Create.
/// </summary>
protected abstract RelationalTypeMapping Clone(
bool? noBackslashEscapes = null,
bool? replaceLineBreaksWithCharFunction = null);

protected override void ConfigureParameter(DbParameter parameter)
{
base.ConfigureParameter(parameter);
Expand All @@ -98,5 +117,52 @@ protected override void ConfigureParameter(DbParameter parameter)
parameter.Value = (string)mySqlJsonString;
}
}

void IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator.Create(
CoreTypeMapping defaultTypeMapping,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
if (defaultTypeMapping is not MySqlStringTypeMapping mysqlDefaultTypeMapping)
{
return;
}

var cloneParameters = new List<string>();

if (NoBackslashEscapes != mysqlDefaultTypeMapping.NoBackslashEscapes)
{
cloneParameters.Add($"noBackslashEscapes: {NoBackslashEscapes}");
}

if (ReplaceLineBreaksWithCharFunction != mysqlDefaultTypeMapping.ReplaceLineBreaksWithCharFunction)
{
cloneParameters.Add($"replaceLineBreaksWithCharFunction: {ReplaceLineBreaksWithCharFunction}");
}

if (cloneParameters.Any())
{
var mainBuilder = parameters.MainBuilder;

mainBuilder.AppendLine(";");

mainBuilder
.Append($"{parameters.TargetName}.TypeMapping = (({GetType().Name}){parameters.TargetName}.TypeMapping).Clone(")
.IncrementIndent();

for (var i = 0; i < cloneParameters.Count; i++)
{
if (i > 0)
{
mainBuilder.AppendLine(",");
}

mainBuilder.Append(cloneParameters[i]);
}

mainBuilder
.AppendLine(")")
.DecrementIndent();
}
}
}
}
76 changes: 73 additions & 3 deletions src/EFCore.MySql/Storage/Internal/MySqlStringTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Licensed under the MIT. See LICENSE in the project root for license information.

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Json;
using Microsoft.EntityFrameworkCore.Utilities;
Expand All @@ -15,7 +18,7 @@ namespace Pomelo.EntityFrameworkCore.MySql.Storage.Internal
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class MySqlStringTypeMapping : MySqlTypeMapping
public class MySqlStringTypeMapping : MySqlTypeMapping, IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator
{
public static MySqlStringTypeMapping Default { get; } = new("varchar", StoreTypePostfix.Size);

Expand Down Expand Up @@ -103,8 +106,18 @@ private static int CalculateSize(bool unicode, int? size)
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new MySqlStringTypeMapping(parameters, MySqlDbType, NoBackslashEscapes, ReplaceLineBreaksWithCharFunction, IsUnquoted, ForceToString);

public virtual RelationalTypeMapping Clone(bool? unquoted = null, bool? forceToString = null)
=> new MySqlStringTypeMapping(Parameters, MySqlDbType, NoBackslashEscapes, ReplaceLineBreaksWithCharFunction, unquoted ?? IsUnquoted, forceToString ?? ForceToString);
public virtual RelationalTypeMapping Clone(
bool? unquoted = null,
bool? forceToString = null,
bool? noBackslashEscapes = null,
bool? replaceLineBreaksWithCharFunction = null)
=> new MySqlStringTypeMapping(
Parameters,
MySqlDbType,
noBackslashEscapes ?? NoBackslashEscapes,
replaceLineBreaksWithCharFunction ?? ReplaceLineBreaksWithCharFunction,
unquoted ?? IsUnquoted,
forceToString ?? ForceToString);

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand Down Expand Up @@ -189,5 +202,62 @@ public static string EscapeBackslashes(string literal, bool escapeBackslashes)
? literal.Replace(@"\", @"\\")
: literal;
}

void IMySqlCSharpRuntimeAnnotationTypeMappingCodeGenerator.Create(
CoreTypeMapping defaultTypeMapping,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
if (defaultTypeMapping is not MySqlStringTypeMapping mysqlDefaultTypeMapping)
{
return;
}

var cloneParameters = new List<string>();

if (IsUnquoted != mysqlDefaultTypeMapping.IsUnquoted)
{
cloneParameters.Add($"unquoted: {IsUnquoted}");
}

if (ForceToString != mysqlDefaultTypeMapping.ForceToString)
{
cloneParameters.Add($"forceToString: {ForceToString}");
}

if (NoBackslashEscapes != mysqlDefaultTypeMapping.NoBackslashEscapes)
{
cloneParameters.Add($"noBackslashEscapes: {NoBackslashEscapes}");
}

if (ReplaceLineBreaksWithCharFunction != mysqlDefaultTypeMapping.ReplaceLineBreaksWithCharFunction)
{
cloneParameters.Add($"replaceLineBreaksWithCharFunction: {ReplaceLineBreaksWithCharFunction}");
}

if (cloneParameters.Any())
{
var mainBuilder = parameters.MainBuilder;

mainBuilder.AppendLine(";");

mainBuilder
.Append($"{parameters.TargetName}.TypeMapping = (({GetType().Name}){parameters.TargetName}.TypeMapping).Clone(")
.IncrementIndent();

for (var i = 0; i < cloneParameters.Count; i++)
{
if (i > 0)
{
mainBuilder.AppendLine(",");
}

mainBuilder.Append(cloneParameters[i]);
}

mainBuilder
.AppendLine(")")
.DecrementIndent();
}
}
}
}

0 comments on commit ee1058b

Please sign in to comment.