SnakeCase,LowerCase, UpperCase Culture fix (#25)

Fixes #19
This commit is contained in:
Arda Terekeci
2020-05-04 13:32:09 +03:00
committed by Shay Rojansky
parent 2bacf92f66
commit 290cc33029
11 changed files with 108 additions and 33 deletions

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Xunit; using Xunit;
@@ -23,6 +24,24 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("fullname", entityType.FindProperty("FullName").GetColumnName()); Assert.Equal("fullname", entityType.FindProperty("FullName").GetColumnName());
} }
[Fact]
public void Column_name_is_rewritten_in_turkish()
{
using var context = CreateContext(CultureInfo.CreateSpecificCulture("tr_TR"));
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("ıd", entityType.FindProperty("Id").GetColumnName());
Assert.Equal("fullname", entityType.FindProperty("FullName").GetColumnName());
}
[Fact]
public void Column_name_is_rewritten_in_invariant()
{
using var context = CreateContext(CultureInfo.InvariantCulture);
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("id", entityType.FindProperty("Id").GetColumnName());
Assert.Equal("fullname", entityType.FindProperty("FullName").GetColumnName());
}
[Fact] [Fact]
public void Primary_key_name_is_rewritten() public void Primary_key_name_is_rewritten()
{ {
@@ -55,6 +74,6 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("ix_simpleblog_fullname", entityType.GetIndexes().Single().GetName()); Assert.Equal("ix_simpleblog_fullname", entityType.GetIndexes().Single().GetName());
} }
TestContext CreateContext() => new TestContext(NamingConventionsExtensions.UseLowerCaseNamingConvention); TestContext CreateContext(CultureInfo culture = null) => new TestContext(builder => builder.UseLowerCaseNamingConvention(culture));
} }
} }

View File

@@ -9,8 +9,7 @@ namespace EFCore.NamingConventions.Test
public class TestContext : DbContext public class TestContext : DbContext
{ {
readonly Func<DbContextOptionsBuilder, DbContextOptionsBuilder> _useNamingConvention; readonly Func<DbContextOptionsBuilder, DbContextOptionsBuilder> _useNamingConvention;
public TestContext(Func<DbContextOptionsBuilder, DbContextOptionsBuilder> useNamingConvention)
public TestContext(Func<DbContextOptionsBuilder, DbContextOptionsBuilder> useNamingConvention)
=> _useNamingConvention = useNamingConvention; => _useNamingConvention = useNamingConvention;
public DbSet<SimpleBlog> Blog { get; set; } public DbSet<SimpleBlog> Blog { get; set; }

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Xunit; using Xunit;
@@ -23,6 +24,24 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("full_name", entityType.FindProperty("FullName").GetColumnName()); Assert.Equal("full_name", entityType.FindProperty("FullName").GetColumnName());
} }
[Fact]
public void Column_name_is_rewritten_in_turkish()
{
using var context = CreateContext(CultureInfo.CreateSpecificCulture("tr_TR"));
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("ıd", entityType.FindProperty("Id").GetColumnName());
Assert.Equal("full_name", entityType.FindProperty("FullName").GetColumnName());
}
[Fact]
public void Column_name_is_rewritten_in_invariant()
{
using var context = CreateContext(CultureInfo.InvariantCulture);
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("id", entityType.FindProperty("Id").GetColumnName());
Assert.Equal("full_name", entityType.FindProperty("FullName").GetColumnName());
}
[Fact] [Fact]
public void Owned_entity_name_is_correct_when_configured() public void Owned_entity_name_is_correct_when_configured()
{ {
@@ -63,6 +82,6 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("ix_simple_blog_full_name", entityType.GetIndexes().Single().GetName()); Assert.Equal("ix_simple_blog_full_name", entityType.GetIndexes().Single().GetName());
} }
TestContext CreateContext() => new TestContext(NamingConventionsExtensions.UseSnakeCaseNamingConvention); TestContext CreateContext(CultureInfo culture = null) => new TestContext(builder => builder.UseSnakeCaseNamingConvention(culture));
} }
} }

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Xunit; using Xunit;
@@ -14,6 +15,22 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("SIMPLEBLOG", entityType.GetTableName()); Assert.Equal("SIMPLEBLOG", entityType.GetTableName());
} }
[Fact]
public void Table_name_is_rewritten_in_turkish()
{
using var context = CreateContext(CultureInfo.CreateSpecificCulture("tr_TR"));
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("SİMPLEBLOG", entityType.GetTableName());
}
[Fact]
public void Table_name_is_rewritten_in_invariant()
{
using var context = CreateContext(CultureInfo.InvariantCulture);
var entityType = context.Model.FindEntityType(typeof(SimpleBlog));
Assert.Equal("SIMPLEBLOG", entityType.GetTableName());
}
[Fact] [Fact]
public void Column_name_is_rewritten() public void Column_name_is_rewritten()
{ {
@@ -55,6 +72,6 @@ namespace EFCore.NamingConventions.Test
Assert.Equal("IX_SIMPLEBLOG_FULLNAME", entityType.GetIndexes().Single().GetName()); Assert.Equal("IX_SIMPLEBLOG_FULLNAME", entityType.GetIndexes().Single().GetName());
} }
TestContext CreateContext() => new TestContext(NamingConventionsExtensions.UseUpperCaseNamingConvention); TestContext CreateContext(CultureInfo culture = null) => new TestContext(builder => builder.UseUpperCaseNamingConvention(culture));
} }
} }

View File

@@ -1,7 +1,12 @@
using System.Globalization;
namespace EFCore.NamingConventions.Internal namespace EFCore.NamingConventions.Internal
{ {
class LowerCaseNameRewriter : NameRewriterBase class LowerCaseNameRewriter : NameRewriterBase
{ {
protected override string RewriteName(string name) => name.ToLowerInvariant(); readonly CultureInfo _culture;
public LowerCaseNameRewriter(CultureInfo culture) => _culture = culture;
protected override string RewriteName(string name) => name.ToLower(_culture);
} }
} }

View File

@@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions;

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Globalization;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
@@ -9,21 +10,20 @@ namespace EFCore.NamingConventions.Internal
public class NamingConventionSetPlugin : IConventionSetPlugin public class NamingConventionSetPlugin : IConventionSetPlugin
{ {
readonly IDbContextOptions _options; readonly IDbContextOptions _options;
public NamingConventionSetPlugin([NotNull] IDbContextOptions options) => _options = options; public NamingConventionSetPlugin([NotNull] IDbContextOptions options) => _options = options;
public ConventionSet ModifyConventions(ConventionSet conventionSet) public ConventionSet ModifyConventions(ConventionSet conventionSet)
{ {
var namingStyle = _options.FindExtension<NamingConventionsOptionsExtension>().NamingConvention; var extension = _options.FindExtension<NamingConventionsOptionsExtension>();
var namingStyle = extension.NamingConvention;
var culture = extension.Culture;
if (namingStyle == NamingConvention.None) if (namingStyle == NamingConvention.None)
return conventionSet; return conventionSet;
NameRewriterBase nameRewriter = namingStyle switch NameRewriterBase nameRewriter = namingStyle switch
{ {
NamingConvention.SnakeCase => new SnakeCaseNameRewriter(), NamingConvention.SnakeCase => new SnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
NamingConvention.LowerCase => new LowerCaseNameRewriter(), NamingConvention.LowerCase => new LowerCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
NamingConvention.UpperCase => new UpperCaseNameRewriter(), NamingConvention.UpperCase => new UpperCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
_ => throw new NotImplementedException("Unhandled enum value: " + namingStyle) _ => throw new NotImplementedException("Unhandled enum value: " + namingStyle)
}; };

View File

@@ -11,17 +11,21 @@ namespace EFCore.NamingConventions.Internal
{ {
DbContextOptionsExtensionInfo _info; DbContextOptionsExtensionInfo _info;
NamingConvention _namingConvention; NamingConvention _namingConvention;
CultureInfo _culture;
public NamingConventionsOptionsExtension() {} public NamingConventionsOptionsExtension() {}
protected NamingConventionsOptionsExtension([NotNull] NamingConventionsOptionsExtension copyFrom) protected NamingConventionsOptionsExtension([NotNull] NamingConventionsOptionsExtension copyFrom)
=> _namingConvention = copyFrom._namingConvention; {
_namingConvention = copyFrom._namingConvention;
_culture = copyFrom._culture;
}
public virtual DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this); public virtual DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
protected virtual NamingConventionsOptionsExtension Clone() => new NamingConventionsOptionsExtension(this); protected virtual NamingConventionsOptionsExtension Clone() => new NamingConventionsOptionsExtension(this);
internal virtual NamingConvention NamingConvention => _namingConvention; internal virtual NamingConvention NamingConvention => _namingConvention;
internal virtual CultureInfo Culture => _culture;
public virtual NamingConventionsOptionsExtension WithoutNaming() public virtual NamingConventionsOptionsExtension WithoutNaming()
{ {
@@ -30,24 +34,27 @@ namespace EFCore.NamingConventions.Internal
return clone; return clone;
} }
public virtual NamingConventionsOptionsExtension WithSnakeCaseNamingConvention() public virtual NamingConventionsOptionsExtension WithSnakeCaseNamingConvention(CultureInfo culture = null)
{ {
var clone = Clone(); var clone = Clone();
clone._namingConvention = NamingConvention.SnakeCase; clone._namingConvention = NamingConvention.SnakeCase;
clone._culture = culture;
return clone; return clone;
} }
public virtual NamingConventionsOptionsExtension WithLowerCaseNamingConvention() public virtual NamingConventionsOptionsExtension WithLowerCaseNamingConvention(CultureInfo culture = null)
{ {
var clone = Clone(); var clone = Clone();
clone._namingConvention = NamingConvention.LowerCase; clone._namingConvention = NamingConvention.LowerCase;
clone._culture = culture;
return clone; return clone;
} }
public virtual NamingConventionsOptionsExtension WithUpperCaseNamingConvention() public virtual NamingConventionsOptionsExtension WithUpperCaseNamingConvention(CultureInfo culture = null)
{ {
var clone = Clone(); var clone = Clone();
clone._namingConvention = NamingConvention.UpperCase; clone._namingConvention = NamingConvention.UpperCase;
clone._culture = culture;
return clone; return clone;
} }

View File

@@ -6,6 +6,10 @@ namespace EFCore.NamingConventions.Internal
{ {
class SnakeCaseNameRewriter : NameRewriterBase class SnakeCaseNameRewriter : NameRewriterBase
{ {
private readonly CultureInfo _culture;
public SnakeCaseNameRewriter(CultureInfo culture) => _culture = culture;
protected override string RewriteName(string name) protected override string RewriteName(string name)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
@@ -40,7 +44,7 @@ namespace EFCore.NamingConventions.Internal
builder.Append('_'); builder.Append('_');
} }
currentChar = char.ToLower(currentChar); currentChar = char.ToLower(currentChar, _culture);
break; break;
case UnicodeCategory.LowercaseLetter: case UnicodeCategory.LowercaseLetter:

View File

@@ -1,7 +1,12 @@
using System.Globalization;
namespace EFCore.NamingConventions.Internal namespace EFCore.NamingConventions.Internal
{ {
class UpperCaseNameRewriter : NameRewriterBase class UpperCaseNameRewriter : NameRewriterBase
{ {
protected override string RewriteName(string name) => name.ToUpperInvariant(); readonly CultureInfo _culture;
public UpperCaseNameRewriter(CultureInfo culture) => _culture = culture;
protected override string RewriteName(string name) => name.ToUpper(_culture);
} }
} }

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using JetBrains.Annotations; using JetBrains.Annotations;
using EFCore.NamingConventions.Internal; using EFCore.NamingConventions.Internal;
@@ -7,52 +8,52 @@ namespace Microsoft.EntityFrameworkCore
{ {
public static class NamingConventionsExtensions public static class NamingConventionsExtensions
{ {
public static DbContextOptionsBuilder UseSnakeCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder) public static DbContextOptionsBuilder UseSnakeCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder , CultureInfo culture = null)
{ {
Check.NotNull(optionsBuilder, nameof(optionsBuilder)); Check.NotNull(optionsBuilder, nameof(optionsBuilder));
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension()) var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension())
.WithSnakeCaseNamingConvention(); .WithSnakeCaseNamingConvention(culture);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return optionsBuilder; return optionsBuilder;
} }
public static DbContextOptionsBuilder<TContext> UseSnakeCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder) public static DbContextOptionsBuilder<TContext> UseSnakeCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder , CultureInfo culture = null)
where TContext : DbContext where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder); => (DbContextOptionsBuilder<TContext>)UseSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder,culture);
public static DbContextOptionsBuilder UseLowerCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder) public static DbContextOptionsBuilder UseLowerCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
{ {
Check.NotNull(optionsBuilder, nameof(optionsBuilder)); Check.NotNull(optionsBuilder, nameof(optionsBuilder));
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension()) var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension())
.WithLowerCaseNamingConvention(); .WithLowerCaseNamingConvention(culture);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return optionsBuilder; return optionsBuilder;
} }
public static DbContextOptionsBuilder<TContext> UseLowerCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder) public static DbContextOptionsBuilder<TContext> UseLowerCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
where TContext : DbContext where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseLowerCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder); => (DbContextOptionsBuilder<TContext>)UseLowerCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder,culture);
public static DbContextOptionsBuilder UseUpperCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder) public static DbContextOptionsBuilder UseUpperCaseNamingConvention([NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
{ {
Check.NotNull(optionsBuilder, nameof(optionsBuilder)); Check.NotNull(optionsBuilder, nameof(optionsBuilder));
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension()) var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension())
.WithUpperCaseNamingConvention(); .WithUpperCaseNamingConvention(culture);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return optionsBuilder; return optionsBuilder;
} }
public static DbContextOptionsBuilder<TContext> UseUpperCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder) public static DbContextOptionsBuilder<TContext> UseUpperCaseNamingConvention<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
where TContext : DbContext where TContext : DbContext
=> (DbContextOptionsBuilder<TContext>)UseUpperCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder); => (DbContextOptionsBuilder<TContext>)UseUpperCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder,culture);
} }
} }