mirror of
https://github.com/fergalmoran/EFCore.NamingConventions.git
synced 2025-12-22 09:38:21 +00:00
File-scoped namespaces
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -2,33 +2,32 @@ using System.Globalization;
|
|||||||
using EFCore.NamingConventions.Internal;
|
using EFCore.NamingConventions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Test
|
namespace EFCore.NamingConventions.Test;
|
||||||
|
|
||||||
|
public class RewriterTest
|
||||||
{
|
{
|
||||||
public class RewriterTest
|
[Fact]
|
||||||
{
|
public void SnakeCase()
|
||||||
[Fact]
|
=> Assert.Equal("full_name",
|
||||||
public void SnakeCase()
|
new SnakeCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
||||||
=> Assert.Equal("full_name",
|
|
||||||
new SnakeCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UpperSnakeCase()
|
public void UpperSnakeCase()
|
||||||
=> Assert.Equal("FULL_NAME",
|
=> Assert.Equal("FULL_NAME",
|
||||||
new UpperSnakeCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
new UpperSnakeCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void LowerCase()
|
public void LowerCase()
|
||||||
=> Assert.Equal("fullname",
|
=> Assert.Equal("fullname",
|
||||||
new LowerCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
new LowerCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CamelCase()
|
public void CamelCase()
|
||||||
=> Assert.Equal("fullName",
|
=> Assert.Equal("fullName",
|
||||||
new CamelCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
new CamelCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UpperCase()
|
public void UpperCase()
|
||||||
=> Assert.Equal("FULLNAME",
|
=> Assert.Equal("FULLNAME",
|
||||||
new UpperCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
new UpperCaseNameRewriter(CultureInfo.InvariantCulture).RewriteName("FullName"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -7,24 +7,23 @@ using Microsoft.EntityFrameworkCore.Sqlite.Diagnostics.Internal;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.EntityFrameworkCore.TestUtilities
|
namespace Microsoft.EntityFrameworkCore.TestUtilities;
|
||||||
|
|
||||||
|
public class SqliteTestHelpers : TestHelpers
|
||||||
{
|
{
|
||||||
public class SqliteTestHelpers : TestHelpers
|
protected SqliteTestHelpers()
|
||||||
{
|
{
|
||||||
protected SqliteTestHelpers()
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SqliteTestHelpers Instance { get; } = new();
|
public static SqliteTestHelpers Instance { get; } = new();
|
||||||
|
|
||||||
public override IServiceCollection AddProviderServices(IServiceCollection services)
|
public override IServiceCollection AddProviderServices(IServiceCollection services)
|
||||||
=> services.AddEntityFrameworkSqlite();
|
=> services.AddEntityFrameworkSqlite();
|
||||||
|
|
||||||
public override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
|
public override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
|
||||||
=> optionsBuilder.UseSqlite(new SqliteConnection("Data Source=:memory:"));
|
=> optionsBuilder.UseSqlite(new SqliteConnection("Data Source=:memory:"));
|
||||||
|
|
||||||
#pragma warning disable EF1001
|
#pragma warning disable EF1001
|
||||||
public override LoggingDefinitions LoggingDefinitions { get; } = new SqliteLoggingDefinitions();
|
public override LoggingDefinitions LoggingDefinitions { get; } = new SqliteLoggingDefinitions();
|
||||||
#pragma warning restore EF1001
|
#pragma warning restore EF1001
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,105 +6,104 @@ using JetBrains.Annotations;
|
|||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.EntityFrameworkCore
|
namespace Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
internal static class Check
|
||||||
{
|
{
|
||||||
[DebuggerStepThrough]
|
[ContractAnnotation("value:null => halt")]
|
||||||
internal static class Check
|
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName)
|
||||||
{
|
{
|
||||||
[ContractAnnotation("value:null => halt")]
|
if (ReferenceEquals(value, null))
|
||||||
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName)
|
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(value, null))
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
|
|
||||||
throw new ArgumentNullException(parameterName);
|
throw new ArgumentNullException(parameterName);
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ContractAnnotation("value:null => halt")]
|
return value;
|
||||||
public static T NotNull<T>(
|
|
||||||
[NoEnumeration] T value,
|
|
||||||
[InvokerParameterName] [NotNull] string parameterName,
|
|
||||||
[NotNull] string propertyName)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(value, null))
|
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
NotEmpty(propertyName, nameof(propertyName));
|
|
||||||
|
|
||||||
throw new ArgumentException(CoreStrings.ArgumentPropertyNull(propertyName, parameterName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ContractAnnotation("value:null => halt")]
|
|
||||||
public static IReadOnlyList<T> NotEmpty<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
|
|
||||||
{
|
|
||||||
NotNull(value, parameterName);
|
|
||||||
|
|
||||||
if (value.Count == 0)
|
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
|
|
||||||
throw new ArgumentException(AbstractionsStrings.CollectionArgumentIsEmpty(parameterName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ContractAnnotation("value:null => halt")]
|
|
||||||
public static string NotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
|
|
||||||
{
|
|
||||||
Exception e = null;
|
|
||||||
if (ReferenceEquals(value, null))
|
|
||||||
{
|
|
||||||
e = new ArgumentNullException(parameterName);
|
|
||||||
}
|
|
||||||
else if (value.Trim().Length == 0)
|
|
||||||
{
|
|
||||||
e = new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e != null)
|
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string NullButNotEmpty([CanBeNull] string value, [InvokerParameterName] [NotNull] string parameterName)
|
|
||||||
{
|
|
||||||
if (!ReferenceEquals(value, null)
|
|
||||||
&& (value.Length == 0))
|
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
|
|
||||||
throw new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IReadOnlyList<T> HasNoNulls<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
NotNull(value, parameterName);
|
|
||||||
|
|
||||||
if (value.Any(e => e == null))
|
|
||||||
{
|
|
||||||
NotEmpty(parameterName, nameof(parameterName));
|
|
||||||
|
|
||||||
throw new ArgumentException(parameterName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
[ContractAnnotation("value:null => halt")]
|
||||||
|
public static T NotNull<T>(
|
||||||
|
[NoEnumeration] T value,
|
||||||
|
[InvokerParameterName] [NotNull] string parameterName,
|
||||||
|
[NotNull] string propertyName)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(value, null))
|
||||||
|
{
|
||||||
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
|
NotEmpty(propertyName, nameof(propertyName));
|
||||||
|
|
||||||
|
throw new ArgumentException(CoreStrings.ArgumentPropertyNull(propertyName, parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ContractAnnotation("value:null => halt")]
|
||||||
|
public static IReadOnlyList<T> NotEmpty<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
|
||||||
|
{
|
||||||
|
NotNull(value, parameterName);
|
||||||
|
|
||||||
|
if (value.Count == 0)
|
||||||
|
{
|
||||||
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
|
|
||||||
|
throw new ArgumentException(AbstractionsStrings.CollectionArgumentIsEmpty(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ContractAnnotation("value:null => halt")]
|
||||||
|
public static string NotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
|
||||||
|
{
|
||||||
|
Exception e = null;
|
||||||
|
if (ReferenceEquals(value, null))
|
||||||
|
{
|
||||||
|
e = new ArgumentNullException(parameterName);
|
||||||
|
}
|
||||||
|
else if (value.Trim().Length == 0)
|
||||||
|
{
|
||||||
|
e = new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string NullButNotEmpty([CanBeNull] string value, [InvokerParameterName] [NotNull] string parameterName)
|
||||||
|
{
|
||||||
|
if (!ReferenceEquals(value, null)
|
||||||
|
&& (value.Length == 0))
|
||||||
|
{
|
||||||
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
|
|
||||||
|
throw new ArgumentException(AbstractionsStrings.ArgumentIsEmpty(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IReadOnlyList<T> HasNoNulls<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
NotNull(value, parameterName);
|
||||||
|
|
||||||
|
if (value.Any(e => e == null))
|
||||||
|
{
|
||||||
|
NotEmpty(parameterName, nameof(parameterName));
|
||||||
|
|
||||||
|
throw new ArgumentException(parameterName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,108 +1,107 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace JetBrains.Annotations
|
namespace JetBrains.Annotations;
|
||||||
|
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field)]
|
||||||
|
internal sealed class NotNullAttribute : Attribute
|
||||||
{
|
{
|
||||||
[AttributeUsage(
|
}
|
||||||
AttributeTargets.Method | AttributeTargets.Parameter |
|
|
||||||
AttributeTargets.Property | AttributeTargets.Delegate |
|
[AttributeUsage(
|
||||||
AttributeTargets.Field)]
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
internal sealed class NotNullAttribute : Attribute
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field)]
|
||||||
|
internal sealed class CanBeNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
internal sealed class InvokerParameterNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
internal sealed class NoEnumerationAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||||
|
internal sealed class ContractAnnotationAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Contract { get; }
|
||||||
|
|
||||||
|
public bool ForceFullStates { get; }
|
||||||
|
|
||||||
|
public ContractAnnotationAttribute([NotNull] string contract)
|
||||||
|
: this(contract, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[AttributeUsage(
|
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
|
||||||
AttributeTargets.Method | AttributeTargets.Parameter |
|
|
||||||
AttributeTargets.Property | AttributeTargets.Delegate |
|
|
||||||
AttributeTargets.Field)]
|
|
||||||
internal sealed class CanBeNullAttribute : Attribute
|
|
||||||
{
|
{
|
||||||
}
|
Contract = contract;
|
||||||
|
ForceFullStates = forceFullStates;
|
||||||
[AttributeUsage(AttributeTargets.Parameter)]
|
|
||||||
internal sealed class InvokerParameterNameAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Parameter)]
|
|
||||||
internal sealed class NoEnumerationAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
|
||||||
internal sealed class ContractAnnotationAttribute : Attribute
|
|
||||||
{
|
|
||||||
public string Contract { get; }
|
|
||||||
|
|
||||||
public bool ForceFullStates { get; }
|
|
||||||
|
|
||||||
public ContractAnnotationAttribute([NotNull] string contract)
|
|
||||||
: this(contract, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
|
|
||||||
{
|
|
||||||
Contract = contract;
|
|
||||||
ForceFullStates = forceFullStates;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.All)]
|
|
||||||
internal sealed class UsedImplicitlyAttribute : Attribute
|
|
||||||
{
|
|
||||||
public UsedImplicitlyAttribute()
|
|
||||||
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
|
|
||||||
: this(useKindFlags, ImplicitUseTargetFlags.Default)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
|
|
||||||
: this(ImplicitUseKindFlags.Default, targetFlags)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public UsedImplicitlyAttribute(
|
|
||||||
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
|
||||||
{
|
|
||||||
UseKindFlags = useKindFlags;
|
|
||||||
TargetFlags = targetFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImplicitUseKindFlags UseKindFlags { get; }
|
|
||||||
public ImplicitUseTargetFlags TargetFlags { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Delegate)]
|
|
||||||
internal sealed class StringFormatMethodAttribute : Attribute
|
|
||||||
{
|
|
||||||
public StringFormatMethodAttribute([NotNull] string formatParameterName)
|
|
||||||
=> FormatParameterName = formatParameterName;
|
|
||||||
|
|
||||||
[NotNull]
|
|
||||||
public string FormatParameterName { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
internal enum ImplicitUseKindFlags
|
|
||||||
{
|
|
||||||
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
|
|
||||||
Access = 1,
|
|
||||||
Assign = 2,
|
|
||||||
InstantiatedWithFixedConstructorSignature = 4,
|
|
||||||
InstantiatedNoFixedConstructorSignature = 8
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
internal enum ImplicitUseTargetFlags
|
|
||||||
{
|
|
||||||
Default = Itself,
|
|
||||||
Itself = 1,
|
|
||||||
Members = 2,
|
|
||||||
WithMembers = Itself | Members
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.All)]
|
||||||
|
internal sealed class UsedImplicitlyAttribute : Attribute
|
||||||
|
{
|
||||||
|
public UsedImplicitlyAttribute()
|
||||||
|
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
|
||||||
|
: this(useKindFlags, ImplicitUseTargetFlags.Default)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
|
||||||
|
: this(ImplicitUseKindFlags.Default, targetFlags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(
|
||||||
|
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
||||||
|
{
|
||||||
|
UseKindFlags = useKindFlags;
|
||||||
|
TargetFlags = targetFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImplicitUseKindFlags UseKindFlags { get; }
|
||||||
|
public ImplicitUseTargetFlags TargetFlags { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Delegate)]
|
||||||
|
internal sealed class StringFormatMethodAttribute : Attribute
|
||||||
|
{
|
||||||
|
public StringFormatMethodAttribute([NotNull] string formatParameterName)
|
||||||
|
=> FormatParameterName = formatParameterName;
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string FormatParameterName { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum ImplicitUseKindFlags
|
||||||
|
{
|
||||||
|
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
|
||||||
|
Access = 1,
|
||||||
|
Assign = 2,
|
||||||
|
InstantiatedWithFixedConstructorSignature = 4,
|
||||||
|
InstantiatedNoFixedConstructorSignature = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum ImplicitUseTargetFlags
|
||||||
|
{
|
||||||
|
Default = Itself,
|
||||||
|
Itself = 1,
|
||||||
|
Members = 2,
|
||||||
|
WithMembers = Itself | Members
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class CamelCaseNameRewriter : INameRewriter
|
||||||
{
|
{
|
||||||
public class CamelCaseNameRewriter : INameRewriter
|
private readonly CultureInfo _culture;
|
||||||
{
|
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
|
|
||||||
public CamelCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
public CamelCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
||||||
|
|
||||||
public string RewriteName(string name) =>
|
public string RewriteName(string name) =>
|
||||||
string.IsNullOrEmpty(name) ? name: char.ToLower(name[0], _culture) + name.Substring(1);
|
string.IsNullOrEmpty(name) ? name: char.ToLower(name[0], _culture) + name.Substring(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public interface INameRewriter
|
||||||
{
|
{
|
||||||
public interface INameRewriter
|
string RewriteName(string name);
|
||||||
{
|
}
|
||||||
string RewriteName(string name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
{
|
|
||||||
public class LowerCaseNameRewriter : INameRewriter
|
|
||||||
{
|
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
|
|
||||||
public LowerCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
public class LowerCaseNameRewriter : INameRewriter
|
||||||
public string RewriteName(string name) => name.ToLower(_culture);
|
{
|
||||||
}
|
private readonly CultureInfo _culture;
|
||||||
}
|
|
||||||
|
public LowerCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
||||||
|
public string RewriteName(string name) => name.ToLower(_culture);
|
||||||
|
}
|
||||||
@@ -5,278 +5,277 @@ using Microsoft.EntityFrameworkCore.Metadata;
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class NameRewritingConvention :
|
||||||
|
IEntityTypeAddedConvention,
|
||||||
|
IEntityTypeAnnotationChangedConvention,
|
||||||
|
IPropertyAddedConvention,
|
||||||
|
IForeignKeyOwnershipChangedConvention,
|
||||||
|
IKeyAddedConvention,
|
||||||
|
IForeignKeyAddedConvention,
|
||||||
|
IIndexAddedConvention,
|
||||||
|
IEntityTypeBaseTypeChangedConvention,
|
||||||
|
IModelFinalizingConvention
|
||||||
{
|
{
|
||||||
public class NameRewritingConvention :
|
private static readonly StoreObjectType[] _storeObjectTypes
|
||||||
IEntityTypeAddedConvention,
|
= { StoreObjectType.Table, StoreObjectType.View, StoreObjectType.Function, StoreObjectType.SqlQuery };
|
||||||
IEntityTypeAnnotationChangedConvention,
|
|
||||||
IPropertyAddedConvention,
|
private readonly INameRewriter _namingNameRewriter;
|
||||||
IForeignKeyOwnershipChangedConvention,
|
|
||||||
IKeyAddedConvention,
|
public NameRewritingConvention(INameRewriter nameRewriter)
|
||||||
IForeignKeyAddedConvention,
|
=> _namingNameRewriter = nameRewriter;
|
||||||
IIndexAddedConvention,
|
|
||||||
IEntityTypeBaseTypeChangedConvention,
|
public virtual void ProcessEntityTypeAdded(
|
||||||
IModelFinalizingConvention
|
IConventionEntityTypeBuilder entityTypeBuilder,
|
||||||
|
IConventionContext<IConventionEntityTypeBuilder> context)
|
||||||
{
|
{
|
||||||
private static readonly StoreObjectType[] _storeObjectTypes
|
var entityType = entityTypeBuilder.Metadata;
|
||||||
= { StoreObjectType.Table, StoreObjectType.View, StoreObjectType.Function, StoreObjectType.SqlQuery };
|
|
||||||
|
|
||||||
private readonly INameRewriter _namingNameRewriter;
|
// Note that the base type is null when the entity type is first added - a base type only gets added later
|
||||||
|
// (see ProcessEntityTypeBaseTypeChanged). But we still have this check for safety.
|
||||||
public NameRewritingConvention(INameRewriter nameRewriter)
|
if (entityType.BaseType is null)
|
||||||
=> _namingNameRewriter = nameRewriter;
|
|
||||||
|
|
||||||
public virtual void ProcessEntityTypeAdded(
|
|
||||||
IConventionEntityTypeBuilder entityTypeBuilder,
|
|
||||||
IConventionContext<IConventionEntityTypeBuilder> context)
|
|
||||||
{
|
{
|
||||||
var entityType = entityTypeBuilder.Metadata;
|
entityTypeBuilder.ToTable(_namingNameRewriter.RewriteName(entityType.GetTableName()), entityType.GetSchema());
|
||||||
|
|
||||||
// Note that the base type is null when the entity type is first added - a base type only gets added later
|
if (entityType.GetViewNameConfigurationSource() == ConfigurationSource.Convention)
|
||||||
// (see ProcessEntityTypeBaseTypeChanged). But we still have this check for safety.
|
|
||||||
if (entityType.BaseType is null)
|
|
||||||
{
|
{
|
||||||
entityTypeBuilder.ToTable(_namingNameRewriter.RewriteName(entityType.GetTableName()), entityType.GetSchema());
|
entityTypeBuilder.ToView(_namingNameRewriter.RewriteName(entityType.GetViewName()), entityType.GetViewSchema());
|
||||||
|
|
||||||
if (entityType.GetViewNameConfigurationSource() == ConfigurationSource.Convention)
|
|
||||||
{
|
|
||||||
entityTypeBuilder.ToView(_namingNameRewriter.RewriteName(entityType.GetViewName()), entityType.GetViewSchema());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ProcessEntityTypeBaseTypeChanged(
|
public void ProcessEntityTypeBaseTypeChanged(
|
||||||
IConventionEntityTypeBuilder entityTypeBuilder,
|
IConventionEntityTypeBuilder entityTypeBuilder,
|
||||||
IConventionEntityType newBaseType,
|
IConventionEntityType newBaseType,
|
||||||
IConventionEntityType oldBaseType,
|
IConventionEntityType oldBaseType,
|
||||||
IConventionContext<IConventionEntityType> context)
|
IConventionContext<IConventionEntityType> context)
|
||||||
|
{
|
||||||
|
var entityType = entityTypeBuilder.Metadata;
|
||||||
|
|
||||||
|
if (newBaseType is null)
|
||||||
{
|
{
|
||||||
var entityType = entityTypeBuilder.Metadata;
|
// The entity is getting removed from a hierarchy. Set the (rewritten) TableName.
|
||||||
|
entityTypeBuilder.ToTable(_namingNameRewriter.RewriteName(entityType.GetTableName()), entityType.GetSchema());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The entity is getting a new base type (e.g. joining a hierarchy).
|
||||||
|
// If this is TPH, we remove the previously rewritten TableName (and non-rewritten Schema) which we set when the
|
||||||
|
// entity type was first added to the model (see ProcessEntityTypeAdded).
|
||||||
|
// If this is TPT, TableName and Schema are set explicitly, so the following will be ignored.
|
||||||
|
entityTypeBuilder.HasNoAnnotation(RelationalAnnotationNames.TableName);
|
||||||
|
entityTypeBuilder.HasNoAnnotation(RelationalAnnotationNames.Schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newBaseType is null)
|
public virtual void ProcessPropertyAdded(
|
||||||
|
IConventionPropertyBuilder propertyBuilder,
|
||||||
|
IConventionContext<IConventionPropertyBuilder> context)
|
||||||
|
=> RewriteColumnName(propertyBuilder);
|
||||||
|
|
||||||
|
public void ProcessForeignKeyOwnershipChanged(IConventionForeignKeyBuilder relationshipBuilder, IConventionContext<bool?> context)
|
||||||
|
{
|
||||||
|
var foreignKey = relationshipBuilder.Metadata;
|
||||||
|
var ownedEntityType = foreignKey.DeclaringEntityType;
|
||||||
|
|
||||||
|
// An entity type is becoming owned - this is a bit complicated.
|
||||||
|
// Unless it's a collection navigation, or the owned entity table name was explicitly set by the user, this triggers table
|
||||||
|
// splitting, which means we need to undo rewriting which we've done previously.
|
||||||
|
if (foreignKey.IsOwnership
|
||||||
|
&& !foreignKey.GetNavigation(false).IsCollection
|
||||||
|
&& ownedEntityType.GetTableNameConfigurationSource() != ConfigurationSource.Explicit)
|
||||||
|
{
|
||||||
|
// Reset the table name which we've set when the entity type was added.
|
||||||
|
// If table splitting was configured by explicitly setting the table name, the following
|
||||||
|
// does nothing.
|
||||||
|
ownedEntityType.Builder.HasNoAnnotation(RelationalAnnotationNames.TableName);
|
||||||
|
ownedEntityType.Builder.HasNoAnnotation(RelationalAnnotationNames.Schema);
|
||||||
|
|
||||||
|
ownedEntityType.FindPrimaryKey()?.Builder.HasNoAnnotation(RelationalAnnotationNames.Name);
|
||||||
|
|
||||||
|
// We've previously set rewritten column names when the entity was originally added (before becoming owned).
|
||||||
|
// These need to be rewritten again to include the owner prefix.
|
||||||
|
foreach (var property in ownedEntityType.GetProperties())
|
||||||
{
|
{
|
||||||
// The entity is getting removed from a hierarchy. Set the (rewritten) TableName.
|
RewriteColumnName(property.Builder);
|
||||||
entityTypeBuilder.ToTable(_namingNameRewriter.RewriteName(entityType.GetTableName()), entityType.GetSchema());
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessEntityTypeAnnotationChanged(
|
||||||
|
IConventionEntityTypeBuilder entityTypeBuilder,
|
||||||
|
string name,
|
||||||
|
IConventionAnnotation annotation,
|
||||||
|
IConventionAnnotation oldAnnotation,
|
||||||
|
IConventionContext<IConventionAnnotation> context)
|
||||||
|
{
|
||||||
|
var entityType = entityTypeBuilder.Metadata;
|
||||||
|
|
||||||
|
// If the View/SqlQuery/Function name is being set on the entity type, and its table name is set by convention, then we assume
|
||||||
|
// we're the one who set the table name back when the entity type was originally added. We now undo this as the entity type
|
||||||
|
// should only be mapped to the View/SqlQuery/Function.
|
||||||
|
if (name is RelationalAnnotationNames.ViewName or RelationalAnnotationNames.SqlQuery or RelationalAnnotationNames.FunctionName
|
||||||
|
&& annotation.Value is not null
|
||||||
|
&& entityType.GetTableNameConfigurationSource() == ConfigurationSource.Convention)
|
||||||
|
{
|
||||||
|
entityType.SetTableName(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != RelationalAnnotationNames.TableName
|
||||||
|
|| StoreObjectIdentifier.Create(entityType, StoreObjectType.Table) is not StoreObjectIdentifier tableIdentifier)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The table's name is changing - rewrite keys, index names
|
||||||
|
|
||||||
|
if (entityType.FindPrimaryKey() is IConventionKey primaryKey)
|
||||||
|
{
|
||||||
|
// We need to rewrite the PK name.
|
||||||
|
// However, this isn't yet supported with TPT, see https://github.com/dotnet/efcore/issues/23444.
|
||||||
|
// So we need to check if the entity is within a TPT hierarchy, or is an owned entity within a TPT hierarchy.
|
||||||
|
|
||||||
|
var rootType = entityType.GetRootType();
|
||||||
|
var isTPT = rootType.GetDerivedTypes().FirstOrDefault() is { } derivedType
|
||||||
|
&& derivedType.GetTableName() != rootType.GetTableName();
|
||||||
|
|
||||||
|
if (entityType.FindRowInternalForeignKeys(tableIdentifier).FirstOrDefault() is null && !isTPT)
|
||||||
|
{
|
||||||
|
primaryKey.Builder.HasName(_namingNameRewriter.RewriteName(primaryKey.GetDefaultName()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The entity is getting a new base type (e.g. joining a hierarchy).
|
// This hierarchy is being transformed into TPT via the explicit setting of the table name.
|
||||||
// If this is TPH, we remove the previously rewritten TableName (and non-rewritten Schema) which we set when the
|
// We not only have to reset our own key name, but also the parents'. Otherwise, the parent's key name
|
||||||
// entity type was first added to the model (see ProcessEntityTypeAdded).
|
// is used as the child's (see RelationalKeyExtensions.GetName), and we get a "duplicate key name in database" error
|
||||||
// If this is TPT, TableName and Schema are set explicitly, so the following will be ignored.
|
// since both parent and child have the same key name;
|
||||||
entityTypeBuilder.HasNoAnnotation(RelationalAnnotationNames.TableName);
|
foreach (var type in entityType.GetRootType().GetDerivedTypesInclusive())
|
||||||
entityTypeBuilder.HasNoAnnotation(RelationalAnnotationNames.Schema);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ProcessPropertyAdded(
|
|
||||||
IConventionPropertyBuilder propertyBuilder,
|
|
||||||
IConventionContext<IConventionPropertyBuilder> context)
|
|
||||||
=> RewriteColumnName(propertyBuilder);
|
|
||||||
|
|
||||||
public void ProcessForeignKeyOwnershipChanged(IConventionForeignKeyBuilder relationshipBuilder, IConventionContext<bool?> context)
|
|
||||||
{
|
|
||||||
var foreignKey = relationshipBuilder.Metadata;
|
|
||||||
var ownedEntityType = foreignKey.DeclaringEntityType;
|
|
||||||
|
|
||||||
// An entity type is becoming owned - this is a bit complicated.
|
|
||||||
// Unless it's a collection navigation, or the owned entity table name was explicitly set by the user, this triggers table
|
|
||||||
// splitting, which means we need to undo rewriting which we've done previously.
|
|
||||||
if (foreignKey.IsOwnership
|
|
||||||
&& !foreignKey.GetNavigation(false).IsCollection
|
|
||||||
&& ownedEntityType.GetTableNameConfigurationSource() != ConfigurationSource.Explicit)
|
|
||||||
{
|
|
||||||
// Reset the table name which we've set when the entity type was added.
|
|
||||||
// If table splitting was configured by explicitly setting the table name, the following
|
|
||||||
// does nothing.
|
|
||||||
ownedEntityType.Builder.HasNoAnnotation(RelationalAnnotationNames.TableName);
|
|
||||||
ownedEntityType.Builder.HasNoAnnotation(RelationalAnnotationNames.Schema);
|
|
||||||
|
|
||||||
ownedEntityType.FindPrimaryKey()?.Builder.HasNoAnnotation(RelationalAnnotationNames.Name);
|
|
||||||
|
|
||||||
// We've previously set rewritten column names when the entity was originally added (before becoming owned).
|
|
||||||
// These need to be rewritten again to include the owner prefix.
|
|
||||||
foreach (var property in ownedEntityType.GetProperties())
|
|
||||||
{
|
{
|
||||||
RewriteColumnName(property.Builder);
|
if (type.FindPrimaryKey() is IConventionKey pk)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessEntityTypeAnnotationChanged(
|
|
||||||
IConventionEntityTypeBuilder entityTypeBuilder,
|
|
||||||
string name,
|
|
||||||
IConventionAnnotation annotation,
|
|
||||||
IConventionAnnotation oldAnnotation,
|
|
||||||
IConventionContext<IConventionAnnotation> context)
|
|
||||||
{
|
|
||||||
var entityType = entityTypeBuilder.Metadata;
|
|
||||||
|
|
||||||
// If the View/SqlQuery/Function name is being set on the entity type, and its table name is set by convention, then we assume
|
|
||||||
// we're the one who set the table name back when the entity type was originally added. We now undo this as the entity type
|
|
||||||
// should only be mapped to the View/SqlQuery/Function.
|
|
||||||
if (name is RelationalAnnotationNames.ViewName or RelationalAnnotationNames.SqlQuery or RelationalAnnotationNames.FunctionName
|
|
||||||
&& annotation.Value is not null
|
|
||||||
&& entityType.GetTableNameConfigurationSource() == ConfigurationSource.Convention)
|
|
||||||
{
|
|
||||||
entityType.SetTableName(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name != RelationalAnnotationNames.TableName
|
|
||||||
|| StoreObjectIdentifier.Create(entityType, StoreObjectType.Table) is not StoreObjectIdentifier tableIdentifier)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The table's name is changing - rewrite keys, index names
|
|
||||||
|
|
||||||
if (entityType.FindPrimaryKey() is IConventionKey primaryKey)
|
|
||||||
{
|
|
||||||
// We need to rewrite the PK name.
|
|
||||||
// However, this isn't yet supported with TPT, see https://github.com/dotnet/efcore/issues/23444.
|
|
||||||
// So we need to check if the entity is within a TPT hierarchy, or is an owned entity within a TPT hierarchy.
|
|
||||||
|
|
||||||
var rootType = entityType.GetRootType();
|
|
||||||
var isTPT = rootType.GetDerivedTypes().FirstOrDefault() is { } derivedType
|
|
||||||
&& derivedType.GetTableName() != rootType.GetTableName();
|
|
||||||
|
|
||||||
if (entityType.FindRowInternalForeignKeys(tableIdentifier).FirstOrDefault() is null && !isTPT)
|
|
||||||
{
|
|
||||||
primaryKey.Builder.HasName(_namingNameRewriter.RewriteName(primaryKey.GetDefaultName()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This hierarchy is being transformed into TPT via the explicit setting of the table name.
|
|
||||||
// We not only have to reset our own key name, but also the parents'. Otherwise, the parent's key name
|
|
||||||
// is used as the child's (see RelationalKeyExtensions.GetName), and we get a "duplicate key name in database" error
|
|
||||||
// since both parent and child have the same key name;
|
|
||||||
foreach (var type in entityType.GetRootType().GetDerivedTypesInclusive())
|
|
||||||
{
|
{
|
||||||
if (type.FindPrimaryKey() is IConventionKey pk)
|
pk.Builder.HasNoAnnotation(RelationalAnnotationNames.Name);
|
||||||
{
|
|
||||||
pk.Builder.HasNoAnnotation(RelationalAnnotationNames.Name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var foreignKey in entityType.GetForeignKeys())
|
|
||||||
{
|
|
||||||
foreignKey.Builder.HasConstraintName(_namingNameRewriter.RewriteName(foreignKey.GetDefaultName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var index in entityType.GetIndexes())
|
|
||||||
{
|
|
||||||
index.Builder.HasDatabaseName(_namingNameRewriter.RewriteName(index.GetDefaultDatabaseName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (annotation?.Value is not null
|
|
||||||
&& entityType.FindOwnership() is IConventionForeignKey ownership
|
|
||||||
&& (string)annotation.Value != ownership.PrincipalEntityType.GetTableName())
|
|
||||||
{
|
|
||||||
// An owned entity's table is being set explicitly - this is the trigger to undo table splitting (which is the default).
|
|
||||||
|
|
||||||
// When the entity became owned, we prefixed all of its properties - we must now undo that.
|
|
||||||
foreach (var property in entityType.GetProperties()
|
|
||||||
.Except(entityType.FindPrimaryKey().Properties)
|
|
||||||
.Where(p => p.Builder.CanSetColumnName(null)))
|
|
||||||
{
|
|
||||||
RewriteColumnName(property.Builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We previously rewrote the owned entity's primary key name, when the owned entity was still in table splitting.
|
|
||||||
// Now that its getting its own table, rewrite the primary key constraint name again.
|
|
||||||
if (entityType.FindPrimaryKey() is IConventionKey key)
|
|
||||||
{
|
|
||||||
key.Builder.HasName(_namingNameRewriter.RewriteName(key.GetDefaultName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessForeignKeyAdded(
|
foreach (var foreignKey in entityType.GetForeignKeys())
|
||||||
IConventionForeignKeyBuilder relationshipBuilder,
|
|
||||||
IConventionContext<IConventionForeignKeyBuilder> context)
|
|
||||||
=> relationshipBuilder.HasConstraintName(_namingNameRewriter.RewriteName(relationshipBuilder.Metadata.GetDefaultName()));
|
|
||||||
|
|
||||||
public void ProcessKeyAdded(IConventionKeyBuilder keyBuilder, IConventionContext<IConventionKeyBuilder> context)
|
|
||||||
=> keyBuilder.HasName(_namingNameRewriter.RewriteName(keyBuilder.Metadata.GetName()));
|
|
||||||
|
|
||||||
public void ProcessIndexAdded(
|
|
||||||
IConventionIndexBuilder indexBuilder,
|
|
||||||
IConventionContext<IConventionIndexBuilder> context)
|
|
||||||
=> indexBuilder.HasDatabaseName(_namingNameRewriter.RewriteName(indexBuilder.Metadata.GetDefaultDatabaseName()));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// EF Core's <see cref="SharedTableConvention" /> runs at model finalization time, and adds entity type prefixes to
|
|
||||||
/// clashing columns. These prefixes also needs to be rewritten by us, so we run after that convention to do that.
|
|
||||||
/// </summary>
|
|
||||||
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
|
|
||||||
{
|
{
|
||||||
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
|
foreignKey.Builder.HasConstraintName(_namingNameRewriter.RewriteName(foreignKey.GetDefaultName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var index in entityType.GetIndexes())
|
||||||
|
{
|
||||||
|
index.Builder.HasDatabaseName(_namingNameRewriter.RewriteName(index.GetDefaultDatabaseName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation?.Value is not null
|
||||||
|
&& entityType.FindOwnership() is IConventionForeignKey ownership
|
||||||
|
&& (string)annotation.Value != ownership.PrincipalEntityType.GetTableName())
|
||||||
|
{
|
||||||
|
// An owned entity's table is being set explicitly - this is the trigger to undo table splitting (which is the default).
|
||||||
|
|
||||||
|
// When the entity became owned, we prefixed all of its properties - we must now undo that.
|
||||||
|
foreach (var property in entityType.GetProperties()
|
||||||
|
.Except(entityType.FindPrimaryKey().Properties)
|
||||||
|
.Where(p => p.Builder.CanSetColumnName(null)))
|
||||||
{
|
{
|
||||||
foreach (var property in entityType.GetProperties())
|
RewriteColumnName(property.Builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We previously rewrote the owned entity's primary key name, when the owned entity was still in table splitting.
|
||||||
|
// Now that its getting its own table, rewrite the primary key constraint name again.
|
||||||
|
if (entityType.FindPrimaryKey() is IConventionKey key)
|
||||||
|
{
|
||||||
|
key.Builder.HasName(_namingNameRewriter.RewriteName(key.GetDefaultName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessForeignKeyAdded(
|
||||||
|
IConventionForeignKeyBuilder relationshipBuilder,
|
||||||
|
IConventionContext<IConventionForeignKeyBuilder> context)
|
||||||
|
=> relationshipBuilder.HasConstraintName(_namingNameRewriter.RewriteName(relationshipBuilder.Metadata.GetDefaultName()));
|
||||||
|
|
||||||
|
public void ProcessKeyAdded(IConventionKeyBuilder keyBuilder, IConventionContext<IConventionKeyBuilder> context)
|
||||||
|
=> keyBuilder.HasName(_namingNameRewriter.RewriteName(keyBuilder.Metadata.GetName()));
|
||||||
|
|
||||||
|
public void ProcessIndexAdded(
|
||||||
|
IConventionIndexBuilder indexBuilder,
|
||||||
|
IConventionContext<IConventionIndexBuilder> context)
|
||||||
|
=> indexBuilder.HasDatabaseName(_namingNameRewriter.RewriteName(indexBuilder.Metadata.GetDefaultDatabaseName()));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EF Core's <see cref="SharedTableConvention" /> runs at model finalization time, and adds entity type prefixes to
|
||||||
|
/// clashing columns. These prefixes also needs to be rewritten by us, so we run after that convention to do that.
|
||||||
|
/// </summary>
|
||||||
|
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
|
||||||
|
{
|
||||||
|
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
|
||||||
|
{
|
||||||
|
foreach (var property in entityType.GetProperties())
|
||||||
|
{
|
||||||
|
var columnName = property.GetColumnBaseName();
|
||||||
|
if (columnName.StartsWith(entityType.ShortName() + '_', StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var columnName = property.GetColumnBaseName();
|
property.Builder.HasColumnName(
|
||||||
|
_namingNameRewriter.RewriteName(entityType.ShortName()) + columnName.Substring(entityType.ShortName().Length));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var storeObjectType in _storeObjectTypes)
|
||||||
|
{
|
||||||
|
var identifier = StoreObjectIdentifier.Create(entityType, storeObjectType);
|
||||||
|
if (identifier is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.GetColumnNameConfigurationSource(identifier.Value) != ConfigurationSource.Convention)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
columnName = property.GetColumnName(identifier.Value);
|
||||||
if (columnName.StartsWith(entityType.ShortName() + '_', StringComparison.Ordinal))
|
if (columnName.StartsWith(entityType.ShortName() + '_', StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
property.Builder.HasColumnName(
|
property.Builder.HasColumnName(
|
||||||
_namingNameRewriter.RewriteName(entityType.ShortName()) + columnName.Substring(entityType.ShortName().Length));
|
_namingNameRewriter.RewriteName(entityType.ShortName())
|
||||||
|
+ columnName.Substring(entityType.ShortName().Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var storeObjectType in _storeObjectTypes)
|
|
||||||
{
|
|
||||||
var identifier = StoreObjectIdentifier.Create(entityType, storeObjectType);
|
|
||||||
if (identifier is null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property.GetColumnNameConfigurationSource(identifier.Value) != ConfigurationSource.Convention)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
columnName = property.GetColumnName(identifier.Value);
|
|
||||||
if (columnName.StartsWith(entityType.ShortName() + '_', StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
property.Builder.HasColumnName(
|
|
||||||
_namingNameRewriter.RewriteName(entityType.ShortName())
|
|
||||||
+ columnName.Substring(entityType.ShortName().Length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RewriteColumnName(IConventionPropertyBuilder propertyBuilder)
|
|
||||||
{
|
|
||||||
var property = propertyBuilder.Metadata;
|
|
||||||
var entityType = property.DeclaringEntityType;
|
|
||||||
|
|
||||||
// Remove any previous setting of the column name we may have done, so we can get the default recalculated below.
|
|
||||||
property.Builder.HasNoAnnotation(RelationalAnnotationNames.ColumnName);
|
|
||||||
|
|
||||||
// TODO: The following is a temporary hack. We should probably just always set the relational override below,
|
|
||||||
// but https://github.com/dotnet/efcore/pull/23834
|
|
||||||
var baseColumnName = StoreObjectIdentifier.Create(property.DeclaringEntityType, StoreObjectType.Table) is { } tableIdentifier
|
|
||||||
? property.GetDefaultColumnName(tableIdentifier)
|
|
||||||
: property.GetDefaultColumnBaseName();
|
|
||||||
propertyBuilder.HasColumnName(_namingNameRewriter.RewriteName(baseColumnName));
|
|
||||||
|
|
||||||
foreach (var storeObjectType in _storeObjectTypes)
|
|
||||||
{
|
|
||||||
var identifier = StoreObjectIdentifier.Create(entityType, storeObjectType);
|
|
||||||
if (identifier is null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property.GetColumnNameConfigurationSource(identifier.Value) == ConfigurationSource.Convention)
|
|
||||||
{
|
|
||||||
propertyBuilder.HasColumnName(
|
|
||||||
_namingNameRewriter.RewriteName(property.GetColumnName(identifier.Value)), identifier.Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RewriteColumnName(IConventionPropertyBuilder propertyBuilder)
|
||||||
|
{
|
||||||
|
var property = propertyBuilder.Metadata;
|
||||||
|
var entityType = property.DeclaringEntityType;
|
||||||
|
|
||||||
|
// Remove any previous setting of the column name we may have done, so we can get the default recalculated below.
|
||||||
|
property.Builder.HasNoAnnotation(RelationalAnnotationNames.ColumnName);
|
||||||
|
|
||||||
|
// TODO: The following is a temporary hack. We should probably just always set the relational override below,
|
||||||
|
// but https://github.com/dotnet/efcore/pull/23834
|
||||||
|
var baseColumnName = StoreObjectIdentifier.Create(property.DeclaringEntityType, StoreObjectType.Table) is { } tableIdentifier
|
||||||
|
? property.GetDefaultColumnName(tableIdentifier)
|
||||||
|
: property.GetDefaultColumnBaseName();
|
||||||
|
propertyBuilder.HasColumnName(_namingNameRewriter.RewriteName(baseColumnName));
|
||||||
|
|
||||||
|
foreach (var storeObjectType in _storeObjectTypes)
|
||||||
|
{
|
||||||
|
var identifier = StoreObjectIdentifier.Create(entityType, storeObjectType);
|
||||||
|
if (identifier is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.GetColumnNameConfigurationSource(identifier.Value) == ConfigurationSource.Convention)
|
||||||
|
{
|
||||||
|
propertyBuilder.HasColumnName(
|
||||||
|
_namingNameRewriter.RewriteName(property.GetColumnName(identifier.Value)), identifier.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public enum NamingConvention
|
||||||
{
|
{
|
||||||
public enum NamingConvention
|
None,
|
||||||
{
|
SnakeCase,
|
||||||
None,
|
LowerCase,
|
||||||
SnakeCase,
|
CamelCase,
|
||||||
LowerCase,
|
UpperCase,
|
||||||
CamelCase,
|
UpperSnakeCase
|
||||||
UpperCase,
|
|
||||||
UpperSnakeCase
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,44 +5,43 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class NamingConventionSetPlugin : IConventionSetPlugin
|
||||||
{
|
{
|
||||||
public class NamingConventionSetPlugin : IConventionSetPlugin
|
private readonly IDbContextOptions _options;
|
||||||
|
public NamingConventionSetPlugin([NotNull] IDbContextOptions options) => _options = options;
|
||||||
|
|
||||||
|
public ConventionSet ModifyConventions(ConventionSet conventionSet)
|
||||||
{
|
{
|
||||||
private readonly IDbContextOptions _options;
|
var extension = _options.FindExtension<NamingConventionsOptionsExtension>();
|
||||||
public NamingConventionSetPlugin([NotNull] IDbContextOptions options) => _options = options;
|
var namingStyle = extension.NamingConvention;
|
||||||
|
var culture = extension.Culture;
|
||||||
public ConventionSet ModifyConventions(ConventionSet conventionSet)
|
if (namingStyle == NamingConvention.None)
|
||||||
{
|
{
|
||||||
var extension = _options.FindExtension<NamingConventionsOptionsExtension>();
|
|
||||||
var namingStyle = extension.NamingConvention;
|
|
||||||
var culture = extension.Culture;
|
|
||||||
if (namingStyle == NamingConvention.None)
|
|
||||||
{
|
|
||||||
return conventionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
var convention = new NameRewritingConvention(namingStyle switch
|
|
||||||
{
|
|
||||||
NamingConvention.SnakeCase => new SnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
|
||||||
NamingConvention.LowerCase => new LowerCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
|
||||||
NamingConvention.CamelCase => new CamelCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
|
||||||
NamingConvention.UpperCase => new UpperCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
|
||||||
NamingConvention.UpperSnakeCase => new UpperSnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
|
||||||
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + namingStyle)
|
|
||||||
});
|
|
||||||
|
|
||||||
conventionSet.EntityTypeAddedConventions.Add(convention);
|
|
||||||
conventionSet.EntityTypeAnnotationChangedConventions.Add(convention);
|
|
||||||
conventionSet.PropertyAddedConventions.Add(convention);
|
|
||||||
conventionSet.ForeignKeyOwnershipChangedConventions.Add(convention);
|
|
||||||
conventionSet.KeyAddedConventions.Add(convention);
|
|
||||||
conventionSet.ForeignKeyAddedConventions.Add(convention);
|
|
||||||
conventionSet.IndexAddedConventions.Add(convention);
|
|
||||||
conventionSet.EntityTypeBaseTypeChangedConventions.Add(convention);
|
|
||||||
conventionSet.ModelFinalizingConventions.Add(convention);
|
|
||||||
|
|
||||||
return conventionSet;
|
return conventionSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var convention = new NameRewritingConvention(namingStyle switch
|
||||||
|
{
|
||||||
|
NamingConvention.SnakeCase => new SnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
||||||
|
NamingConvention.LowerCase => new LowerCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
||||||
|
NamingConvention.CamelCase => new CamelCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
||||||
|
NamingConvention.UpperCase => new UpperCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
||||||
|
NamingConvention.UpperSnakeCase => new UpperSnakeCaseNameRewriter(culture ?? CultureInfo.InvariantCulture),
|
||||||
|
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + namingStyle)
|
||||||
|
});
|
||||||
|
|
||||||
|
conventionSet.EntityTypeAddedConventions.Add(convention);
|
||||||
|
conventionSet.EntityTypeAnnotationChangedConventions.Add(convention);
|
||||||
|
conventionSet.PropertyAddedConventions.Add(convention);
|
||||||
|
conventionSet.ForeignKeyOwnershipChangedConventions.Add(convention);
|
||||||
|
conventionSet.KeyAddedConventions.Add(convention);
|
||||||
|
conventionSet.ForeignKeyAddedConventions.Add(convention);
|
||||||
|
conventionSet.IndexAddedConventions.Add(convention);
|
||||||
|
conventionSet.EntityTypeBaseTypeChangedConventions.Add(convention);
|
||||||
|
conventionSet.ModelFinalizingConventions.Add(convention);
|
||||||
|
|
||||||
|
return conventionSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,144 +6,143 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class NamingConventionsOptionsExtension : IDbContextOptionsExtension
|
||||||
{
|
{
|
||||||
public class NamingConventionsOptionsExtension : IDbContextOptionsExtension
|
private DbContextOptionsExtensionInfo _info;
|
||||||
|
private NamingConvention _namingConvention;
|
||||||
|
private CultureInfo _culture;
|
||||||
|
|
||||||
|
public NamingConventionsOptionsExtension() {}
|
||||||
|
protected NamingConventionsOptionsExtension([NotNull] NamingConventionsOptionsExtension copyFrom)
|
||||||
{
|
{
|
||||||
private DbContextOptionsExtensionInfo _info;
|
_namingConvention = copyFrom._namingConvention;
|
||||||
private NamingConvention _namingConvention;
|
_culture = copyFrom._culture;
|
||||||
private CultureInfo _culture;
|
}
|
||||||
|
|
||||||
public NamingConventionsOptionsExtension() {}
|
public virtual DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
|
||||||
protected NamingConventionsOptionsExtension([NotNull] NamingConventionsOptionsExtension copyFrom)
|
|
||||||
|
protected virtual NamingConventionsOptionsExtension Clone() => new(this);
|
||||||
|
|
||||||
|
internal virtual NamingConvention NamingConvention => _namingConvention;
|
||||||
|
internal virtual CultureInfo Culture => _culture;
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithoutNaming()
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.None;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithSnakeCaseNamingConvention(CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.SnakeCase;
|
||||||
|
clone._culture = culture;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithLowerCaseNamingConvention(CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.LowerCase;
|
||||||
|
clone._culture = culture;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithUpperCaseNamingConvention(CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.UpperCase;
|
||||||
|
clone._culture = culture;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithUpperSnakeCaseNamingConvention(CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.UpperSnakeCase;
|
||||||
|
clone._culture = culture;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual NamingConventionsOptionsExtension WithCamelCaseNamingConvention(CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
var clone = Clone();
|
||||||
|
clone._namingConvention = NamingConvention.CamelCase;
|
||||||
|
clone._culture = culture;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(IDbContextOptions options) {}
|
||||||
|
|
||||||
|
public void ApplyServices(IServiceCollection services)
|
||||||
|
=> services.AddEntityFrameworkNamingConventions();
|
||||||
|
|
||||||
|
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
|
||||||
|
{
|
||||||
|
private string _logFragment;
|
||||||
|
|
||||||
|
public ExtensionInfo(IDbContextOptionsExtension extension) : base(extension) {}
|
||||||
|
|
||||||
|
private new NamingConventionsOptionsExtension Extension
|
||||||
|
=> (NamingConventionsOptionsExtension)base.Extension;
|
||||||
|
|
||||||
|
public override bool IsDatabaseProvider => false;
|
||||||
|
|
||||||
|
public override string LogFragment
|
||||||
{
|
{
|
||||||
_namingConvention = copyFrom._namingConvention;
|
get
|
||||||
_culture = copyFrom._culture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
|
|
||||||
|
|
||||||
protected virtual NamingConventionsOptionsExtension Clone() => new(this);
|
|
||||||
|
|
||||||
internal virtual NamingConvention NamingConvention => _namingConvention;
|
|
||||||
internal virtual CultureInfo Culture => _culture;
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithoutNaming()
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.None;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithSnakeCaseNamingConvention(CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.SnakeCase;
|
|
||||||
clone._culture = culture;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithLowerCaseNamingConvention(CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.LowerCase;
|
|
||||||
clone._culture = culture;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithUpperCaseNamingConvention(CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.UpperCase;
|
|
||||||
clone._culture = culture;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithUpperSnakeCaseNamingConvention(CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.UpperSnakeCase;
|
|
||||||
clone._culture = culture;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual NamingConventionsOptionsExtension WithCamelCaseNamingConvention(CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
var clone = Clone();
|
|
||||||
clone._namingConvention = NamingConvention.CamelCase;
|
|
||||||
clone._culture = culture;
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate(IDbContextOptions options) {}
|
|
||||||
|
|
||||||
public void ApplyServices(IServiceCollection services)
|
|
||||||
=> services.AddEntityFrameworkNamingConventions();
|
|
||||||
|
|
||||||
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
|
|
||||||
{
|
|
||||||
private string _logFragment;
|
|
||||||
|
|
||||||
public ExtensionInfo(IDbContextOptionsExtension extension) : base(extension) {}
|
|
||||||
|
|
||||||
private new NamingConventionsOptionsExtension Extension
|
|
||||||
=> (NamingConventionsOptionsExtension)base.Extension;
|
|
||||||
|
|
||||||
public override bool IsDatabaseProvider => false;
|
|
||||||
|
|
||||||
public override string LogFragment
|
|
||||||
{
|
{
|
||||||
get
|
if (_logFragment == null)
|
||||||
{
|
{
|
||||||
if (_logFragment == null)
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.Append(Extension._namingConvention switch
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
NamingConvention.SnakeCase => "using snake-case naming ",
|
||||||
|
NamingConvention.LowerCase => "using lower case naming",
|
||||||
|
NamingConvention.UpperCase => "using upper case naming",
|
||||||
|
NamingConvention.UpperSnakeCase => "using upper snake-case naming",
|
||||||
|
NamingConvention.CamelCase => "using camel-case naming",
|
||||||
|
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + Extension._namingConvention)
|
||||||
|
});
|
||||||
|
|
||||||
builder.Append(Extension._namingConvention switch
|
if (Extension._culture is null)
|
||||||
{
|
{
|
||||||
NamingConvention.SnakeCase => "using snake-case naming ",
|
builder
|
||||||
NamingConvention.LowerCase => "using lower case naming",
|
.Append(" (culture=")
|
||||||
NamingConvention.UpperCase => "using upper case naming",
|
.Append(Extension._culture)
|
||||||
NamingConvention.UpperSnakeCase => "using upper snake-case naming",
|
.Append(")");
|
||||||
NamingConvention.CamelCase => "using camel-case naming",
|
|
||||||
_ => throw new ArgumentOutOfRangeException("Unhandled enum value: " + Extension._namingConvention)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Extension._culture is null)
|
|
||||||
{
|
|
||||||
builder
|
|
||||||
.Append(" (culture=")
|
|
||||||
.Append(Extension._culture)
|
|
||||||
.Append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logFragment = builder.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _logFragment;
|
_logFragment = builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _logFragment;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetServiceProviderHashCode()
|
public override int GetServiceProviderHashCode()
|
||||||
|
{
|
||||||
|
var hashCode = Extension._namingConvention.GetHashCode();
|
||||||
|
hashCode = (hashCode * 3) ^ (Extension._culture?.GetHashCode() ?? 0);
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
|
||||||
|
=> other is ExtensionInfo;
|
||||||
|
|
||||||
|
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
|
||||||
|
{
|
||||||
|
debugInfo["Naming:UseNamingConvention"]
|
||||||
|
= Extension._namingConvention.GetHashCode().ToString(CultureInfo.InvariantCulture);
|
||||||
|
if (Extension._culture != null)
|
||||||
{
|
{
|
||||||
var hashCode = Extension._namingConvention.GetHashCode();
|
debugInfo["Naming:Culture"]
|
||||||
hashCode = (hashCode * 3) ^ (Extension._culture?.GetHashCode() ?? 0);
|
= Extension._culture.GetHashCode().ToString(CultureInfo.InvariantCulture);
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
|
|
||||||
=> other is ExtensionInfo;
|
|
||||||
|
|
||||||
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
|
|
||||||
{
|
|
||||||
debugInfo["Naming:UseNamingConvention"]
|
|
||||||
= Extension._namingConvention.GetHashCode().ToString(CultureInfo.InvariantCulture);
|
|
||||||
if (Extension._culture != null)
|
|
||||||
{
|
|
||||||
debugInfo["Naming:Culture"]
|
|
||||||
= Extension._culture.GetHashCode().ToString(CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,37 +2,37 @@ using System;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class SnakeCaseNameRewriter : INameRewriter
|
||||||
{
|
{
|
||||||
public class SnakeCaseNameRewriter : INameRewriter
|
private readonly CultureInfo _culture;
|
||||||
|
|
||||||
|
public SnakeCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
||||||
|
|
||||||
|
public virtual string RewriteName(string name)
|
||||||
{
|
{
|
||||||
private readonly CultureInfo _culture;
|
if (string.IsNullOrEmpty(name))
|
||||||
|
|
||||||
public SnakeCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
|
||||||
|
|
||||||
public virtual string RewriteName(string name)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name))
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new StringBuilder(name.Length + Math.Min(2, name.Length / 5));
|
||||||
|
var previousCategory = default(UnicodeCategory?);
|
||||||
|
|
||||||
|
for (var currentIndex = 0; currentIndex < name.Length; currentIndex++)
|
||||||
|
{
|
||||||
|
var currentChar = name[currentIndex];
|
||||||
|
if (currentChar == '_')
|
||||||
{
|
{
|
||||||
return name;
|
builder.Append('_');
|
||||||
|
previousCategory = null;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new StringBuilder(name.Length + Math.Min(2, name.Length / 5));
|
var currentCategory = char.GetUnicodeCategory(currentChar);
|
||||||
var previousCategory = default(UnicodeCategory?);
|
switch (currentCategory)
|
||||||
|
|
||||||
for (var currentIndex = 0; currentIndex < name.Length; currentIndex++)
|
|
||||||
{
|
{
|
||||||
var currentChar = name[currentIndex];
|
|
||||||
if (currentChar == '_')
|
|
||||||
{
|
|
||||||
builder.Append('_');
|
|
||||||
previousCategory = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentCategory = char.GetUnicodeCategory(currentChar);
|
|
||||||
switch (currentCategory)
|
|
||||||
{
|
|
||||||
case UnicodeCategory.UppercaseLetter:
|
case UnicodeCategory.UppercaseLetter:
|
||||||
case UnicodeCategory.TitlecaseLetter:
|
case UnicodeCategory.TitlecaseLetter:
|
||||||
if (previousCategory == UnicodeCategory.SpaceSeparator ||
|
if (previousCategory == UnicodeCategory.SpaceSeparator ||
|
||||||
@@ -63,13 +63,12 @@ namespace EFCore.NamingConventions.Internal
|
|||||||
previousCategory = UnicodeCategory.SpaceSeparator;
|
previousCategory = UnicodeCategory.SpaceSeparator;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append(currentChar);
|
|
||||||
previousCategory = currentCategory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.ToString();
|
builder.Append(currentChar);
|
||||||
|
previousCategory = currentCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
{
|
|
||||||
public class UpperCaseNameRewriter : INameRewriter
|
|
||||||
{
|
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
|
|
||||||
public UpperCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
public class UpperCaseNameRewriter : INameRewriter
|
||||||
public string RewriteName(string name) => name.ToUpper(_culture);
|
{
|
||||||
}
|
private readonly CultureInfo _culture;
|
||||||
}
|
|
||||||
|
public UpperCaseNameRewriter(CultureInfo culture) => _culture = culture;
|
||||||
|
public string RewriteName(string name) => name.ToUpper(_culture);
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace EFCore.NamingConventions.Internal
|
namespace EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
|
public class UpperSnakeCaseNameRewriter : SnakeCaseNameRewriter
|
||||||
{
|
{
|
||||||
public class UpperSnakeCaseNameRewriter : SnakeCaseNameRewriter
|
private readonly CultureInfo _culture;
|
||||||
{
|
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
|
|
||||||
public UpperSnakeCaseNameRewriter(CultureInfo culture) : base(culture) => _culture = culture;
|
public UpperSnakeCaseNameRewriter(CultureInfo culture) : base(culture) => _culture = culture;
|
||||||
|
|
||||||
public override string RewriteName(string name) => base.RewriteName(name).ToUpper(_culture);
|
public override string RewriteName(string name) => base.RewriteName(name).ToUpper(_culture);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -4,103 +4,102 @@ using JetBrains.Annotations;
|
|||||||
using EFCore.NamingConventions.Internal;
|
using EFCore.NamingConventions.Internal;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.EntityFrameworkCore
|
namespace Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public static class NamingConventionsExtensions
|
||||||
{
|
{
|
||||||
public static class NamingConventionsExtensions
|
public static DbContextOptionsBuilder UseSnakeCaseNamingConvention(
|
||||||
|
[NotNull] this DbContextOptionsBuilder optionsBuilder , CultureInfo culture = null)
|
||||||
{
|
{
|
||||||
public static DbContextOptionsBuilder UseSnakeCaseNamingConvention(
|
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||||
[NotNull] this DbContextOptionsBuilder optionsBuilder , CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
|
||||||
|
|
||||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
||||||
?? new NamingConventionsOptionsExtension())
|
?? new NamingConventionsOptionsExtension())
|
||||||
.WithSnakeCaseNamingConvention(culture);
|
.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 , CultureInfo culture = null)
|
|
||||||
where TContext : DbContext
|
|
||||||
=> (DbContextOptionsBuilder<TContext>)UseSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder UseLowerCaseNamingConvention(
|
|
||||||
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
|
||||||
|
|
||||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
|
||||||
?? new NamingConventionsOptionsExtension())
|
|
||||||
.WithLowerCaseNamingConvention(culture);
|
|
||||||
|
|
||||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder<TContext> UseLowerCaseNamingConvention<TContext>(
|
|
||||||
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
|
||||||
where TContext : DbContext
|
|
||||||
=> (DbContextOptionsBuilder<TContext>)UseLowerCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder ,culture);
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder UseUpperCaseNamingConvention(
|
|
||||||
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
|
||||||
|
|
||||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
|
||||||
?? new NamingConventionsOptionsExtension())
|
|
||||||
.WithUpperCaseNamingConvention(culture);
|
|
||||||
|
|
||||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder<TContext> UseUpperCaseNamingConvention<TContext>(
|
|
||||||
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
|
||||||
where TContext : DbContext
|
|
||||||
=> (DbContextOptionsBuilder<TContext>)UseUpperCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder UseUpperSnakeCaseNamingConvention(
|
|
||||||
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
|
||||||
|
|
||||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
|
||||||
?? new NamingConventionsOptionsExtension())
|
|
||||||
.WithUpperSnakeCaseNamingConvention(culture);
|
|
||||||
|
|
||||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder<TContext> UseUpperSnakeCaseNamingConvention<TContext>(
|
|
||||||
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
|
||||||
where TContext : DbContext
|
|
||||||
=> (DbContextOptionsBuilder<TContext>)UseUpperSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder UseCamelCaseNamingConvention(
|
|
||||||
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
|
||||||
{
|
|
||||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
|
||||||
|
|
||||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
|
||||||
?? new NamingConventionsOptionsExtension())
|
|
||||||
.WithCamelCaseNamingConvention(culture);
|
|
||||||
|
|
||||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
|
||||||
|
|
||||||
return optionsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DbContextOptionsBuilder<TContext> UseCamelCaseNamingConvention<TContext>(
|
|
||||||
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
|
||||||
where TContext : DbContext
|
|
||||||
=> (DbContextOptionsBuilder<TContext>)UseCamelCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static DbContextOptionsBuilder<TContext> UseSnakeCaseNamingConvention<TContext>(
|
||||||
|
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder , CultureInfo culture = null)
|
||||||
|
where TContext : DbContext
|
||||||
|
=> (DbContextOptionsBuilder<TContext>)UseSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder UseLowerCaseNamingConvention(
|
||||||
|
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||||
|
|
||||||
|
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
||||||
|
?? new NamingConventionsOptionsExtension())
|
||||||
|
.WithLowerCaseNamingConvention(culture);
|
||||||
|
|
||||||
|
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||||
|
|
||||||
|
return optionsBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder<TContext> UseLowerCaseNamingConvention<TContext>(
|
||||||
|
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
||||||
|
where TContext : DbContext
|
||||||
|
=> (DbContextOptionsBuilder<TContext>)UseLowerCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder ,culture);
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder UseUpperCaseNamingConvention(
|
||||||
|
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||||
|
|
||||||
|
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
||||||
|
?? new NamingConventionsOptionsExtension())
|
||||||
|
.WithUpperCaseNamingConvention(culture);
|
||||||
|
|
||||||
|
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||||
|
|
||||||
|
return optionsBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder<TContext> UseUpperCaseNamingConvention<TContext>(
|
||||||
|
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
||||||
|
where TContext : DbContext
|
||||||
|
=> (DbContextOptionsBuilder<TContext>)UseUpperCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder UseUpperSnakeCaseNamingConvention(
|
||||||
|
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||||
|
|
||||||
|
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
||||||
|
?? new NamingConventionsOptionsExtension())
|
||||||
|
.WithUpperSnakeCaseNamingConvention(culture);
|
||||||
|
|
||||||
|
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||||
|
|
||||||
|
return optionsBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder<TContext> UseUpperSnakeCaseNamingConvention<TContext>(
|
||||||
|
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
||||||
|
where TContext : DbContext
|
||||||
|
=> (DbContextOptionsBuilder<TContext>)UseUpperSnakeCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder UseCamelCaseNamingConvention(
|
||||||
|
[NotNull] this DbContextOptionsBuilder optionsBuilder, CultureInfo culture = null)
|
||||||
|
{
|
||||||
|
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||||
|
|
||||||
|
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>()
|
||||||
|
?? new NamingConventionsOptionsExtension())
|
||||||
|
.WithCamelCaseNamingConvention(culture);
|
||||||
|
|
||||||
|
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||||
|
|
||||||
|
return optionsBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder<TContext> UseCamelCaseNamingConvention<TContext>(
|
||||||
|
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder, CultureInfo culture = null)
|
||||||
|
where TContext : DbContext
|
||||||
|
=> (DbContextOptionsBuilder<TContext>)UseCamelCaseNamingConvention((DbContextOptionsBuilder)optionsBuilder, culture);
|
||||||
|
}
|
||||||
@@ -5,38 +5,37 @@ using EFCore.NamingConventions.Internal;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
namespace Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class NamingConventionsServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extension methods for <see cref="Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
|
/// <para>
|
||||||
|
/// Adds the services required for applying naming conventions in Entity Framework Core.
|
||||||
|
/// You use this method when using dependency injection in your application, such as with ASP.NET.
|
||||||
|
/// For more information on setting up dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// You only need to use this functionality when you want Entity Framework to resolve the services it uses
|
||||||
|
/// from an external dependency injection container. If you are not using an external
|
||||||
|
/// dependency injection container, Entity Framework will take care of creating the services it requires.
|
||||||
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class NamingConventionsServiceCollectionExtensions
|
/// <param name="serviceCollection">The <see cref="IServiceCollection" /> to add services to.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The same service collection so that multiple calls can be chained.
|
||||||
|
/// </returns>
|
||||||
|
public static IServiceCollection AddEntityFrameworkNamingConventions(
|
||||||
|
[NotNull] this IServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
/// <summary>
|
Check.NotNull(serviceCollection, nameof(serviceCollection));
|
||||||
/// <para>
|
|
||||||
/// Adds the services required for applying naming conventions in Entity Framework Core.
|
|
||||||
/// You use this method when using dependency injection in your application, such as with ASP.NET.
|
|
||||||
/// For more information on setting up dependency injection, see http://go.microsoft.com/fwlink/?LinkId=526890.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// You only need to use this functionality when you want Entity Framework to resolve the services it uses
|
|
||||||
/// from an external dependency injection container. If you are not using an external
|
|
||||||
/// dependency injection container, Entity Framework will take care of creating the services it requires.
|
|
||||||
/// </para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serviceCollection">The <see cref="IServiceCollection" /> to add services to.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// The same service collection so that multiple calls can be chained.
|
|
||||||
/// </returns>
|
|
||||||
public static IServiceCollection AddEntityFrameworkNamingConventions(
|
|
||||||
[NotNull] this IServiceCollection serviceCollection)
|
|
||||||
{
|
|
||||||
Check.NotNull(serviceCollection, nameof(serviceCollection));
|
|
||||||
|
|
||||||
new EntityFrameworkServicesBuilder(serviceCollection)
|
new EntityFrameworkServicesBuilder(serviceCollection)
|
||||||
.TryAdd<IConventionSetPlugin, NamingConventionSetPlugin>();
|
.TryAdd<IConventionSetPlugin, NamingConventionSetPlugin>();
|
||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user