mirror of
https://github.com/fergalmoran/EFCore.NamingConventions.git
synced 2025-12-22 01:28:13 +00:00
Initial commit
This commit is contained in:
40
.editorconfig
Normal file
40
.editorconfig
Normal file
@@ -0,0 +1,40 @@
|
||||
; Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
; Unix-style newlines
|
||||
[*]
|
||||
end_of_line = LF
|
||||
|
||||
; 4-column space indentation
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
; trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.cs]
|
||||
dotnet_style_qualification_for_field = false:error
|
||||
dotnet_style_qualification_for_property = false:error
|
||||
dotnet_style_qualification_for_method = false:error
|
||||
dotnet_style_qualification_for_event = false:error
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:error
|
||||
dotnet_style_predefined_type_for_member_access = true:error
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
csharp_style_var_for_built_in_types = true:error
|
||||
csharp_style_var_when_type_is_apparent = true:error
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
csharp_style_expression_bodied_methods = true:suggestion
|
||||
csharp_style_expression_bodied_constructors = true:suggestion
|
||||
csharp_style_expression_bodied_operators = true:suggestion
|
||||
csharp_style_expression_bodied_properties = true:suggestion
|
||||
csharp_style_expression_bodied_indexers = true:suggestion
|
||||
csharp_style_expression_bodied_accessors = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_indent_case_contents_when_block = false
|
||||
10
.gitattributes
vendored
Normal file
10
.gitattributes
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
* text=auto
|
||||
|
||||
*.cs text=auto diff=csharp
|
||||
*.csproj text=auto
|
||||
*.sln text=auto
|
||||
*.resx text=auto
|
||||
*.xml text=auto
|
||||
*.txt text=auto
|
||||
|
||||
packages/ binary
|
||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
*.resources
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
*.userprefs
|
||||
/*.nupkg
|
||||
.nuget/
|
||||
.idea/
|
||||
[Bb]in/
|
||||
[Bb]uild/
|
||||
[Oo]bj/
|
||||
[Oo]bj/
|
||||
packages/*/
|
||||
Packages/*/
|
||||
packages.stable
|
||||
artifacts/
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
.vs/
|
||||
TestResult.xml
|
||||
13
Directory.Build.props
Normal file
13
Directory.Build.props
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<EFCoreVersion>3.0.0-preview9.19423.6</EFCoreVersion>
|
||||
<MicrosoftExtensionsVersion>3.0.0-preview9.19423.4</MicrosoftExtensionsVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(EFCoreVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EFCore.NamingConventions\EFCore.NamingConventions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
41
EFCore.NamingConventions.Test/NamingConventionsTest.cs
Normal file
41
EFCore.NamingConventions.Test/NamingConventionsTest.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Xunit;
|
||||
|
||||
namespace EFCore.Naming.Test
|
||||
{
|
||||
public class NamingTest
|
||||
{
|
||||
[Fact]
|
||||
public void Table_name_is_rewritten()
|
||||
{
|
||||
using var context = new TestContext();
|
||||
var entityType = context.Model.FindEntityType(typeof(Blog));
|
||||
Assert.Equal("blog", entityType.GetTableName());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_name_is_rewritten()
|
||||
{
|
||||
using var context = new TestContext();
|
||||
var entityType = context.Model.FindEntityType(typeof(Blog));
|
||||
Assert.Equal("id", entityType.FindProperty("Id").GetColumnName());
|
||||
Assert.Equal("full_name", entityType.FindProperty("FullName").GetColumnName());
|
||||
}
|
||||
|
||||
public class TestContext : DbContext
|
||||
{
|
||||
public DbSet<Blog> Blog { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder
|
||||
.UseInMemoryDatabase("test")
|
||||
.UseSnakeCaseNamingConventions();
|
||||
}
|
||||
|
||||
public class Blog
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string FullName { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
24
EFCore.NamingConventions.sln
Normal file
24
EFCore.NamingConventions.sln
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.NamingConventions", "EFCore.NamingConventions\EFCore.NamingConventions.csproj", "{F7AE70A6-D237-4257-84F4-A32375E78E10}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.NamingConventions.Test", "EFCore.NamingConventions.Test\EFCore.NamingConventions.Test.csproj", "{AF58C6DC-FF41-4019-B4F3-B8D59A2DAD5F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F7AE70A6-D237-4257-84F4-A32375E78E10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F7AE70A6-D237-4257-84F4-A32375E78E10}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F7AE70A6-D237-4257-84F4-A32375E78E10}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F7AE70A6-D237-4257-84F4-A32375E78E10}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF58C6DC-FF41-4019-B4F3-B8D59A2DAD5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF58C6DC-FF41-4019-B4F3-B8D59A2DAD5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF58C6DC-FF41-4019-B4F3-B8D59A2DAD5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF58C6DC-FF41-4019-B4F3-B8D59A2DAD5F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
24
EFCore.NamingConventions.sln.DotSettings
Normal file
24
EFCore.NamingConventions.sln.DotSettings
Normal file
@@ -0,0 +1,24 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
|
||||
<!-- Code editing -->
|
||||
<s:String x:Key="/Default/CodeEditing/Localization/Localizable/@EntryValue">No</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/ReadSettingsFromFileLevel/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/UsageCheckingInspectionLevel/@EntryValue">InternalsOnly</s:String>
|
||||
|
||||
<!-- Code inspection -->
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ImplicitNullability/Enabled/@EntryValue">True</s:Boolean>
|
||||
|
||||
<!-- C# formatting -->
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_CASE_FROM_SWITCH/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Npgsql/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rewriter/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
</wpf:ResourceDictionary>
|
||||
BIN
EFCore.NamingConventions.snk
Normal file
BIN
EFCore.NamingConventions.snk
Normal file
Binary file not shown.
110
EFCore.NamingConventions/Check.cs
Normal file
110
EFCore.NamingConventions/Check.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.EntityFrameworkCore
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
internal static class Check
|
||||
{
|
||||
[ContractAnnotation("value:null => halt")]
|
||||
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName)
|
||||
{
|
||||
if (ReferenceEquals(value, null))
|
||||
{
|
||||
NotEmpty(parameterName, nameof(parameterName));
|
||||
|
||||
throw new ArgumentNullException(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
EFCore.NamingConventions/CodeAnnotations.cs
Normal file
108
EFCore.NamingConventions/CodeAnnotations.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
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 |
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
27
EFCore.NamingConventions/EFCore.NamingConventions.csproj
Normal file
27
EFCore.NamingConventions/EFCore.NamingConventions.csproj
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>EFCore.NamingConventions</AssemblyName>
|
||||
<RootNamespace>EFCore</RootNamespace>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<VersionPrefix>1.0.0</VersionPrefix>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<AssemblyOriginatorKeyFile>../EFCore.NamingConventions.snk</AssemblyOriginatorKeyFile>
|
||||
<Description>Naming Conventions for Entity Framework Core Tables and Columns.</Description>
|
||||
<Authors>Shay Rojansky</Authors>
|
||||
<Copyright>Copyright 2019 © Shay Rojansky</Copyright>
|
||||
<PackageTags>Entity Framework Core;entity-framework-core;ef;efcore;orm;sql;postgresql;npgsql</PackageTags>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>git://github.com/efcore/EFCore.NamingConventions</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsVersion)" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="$(EFCoreVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EFCore.NamingConventions.Internal
|
||||
{
|
||||
enum NamingConvention
|
||||
{
|
||||
None,
|
||||
SnakeCase
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace EFCore.NamingConventions.Internal
|
||||
{
|
||||
public class NamingConventionSetPlugin : IConventionSetPlugin
|
||||
{
|
||||
readonly IDbContextOptions _options;
|
||||
|
||||
public NamingConventionSetPlugin([NotNull] IDbContextOptions options) => _options = options;
|
||||
|
||||
public ConventionSet ModifyConventions(ConventionSet conventionSet)
|
||||
{
|
||||
var namingStyle = _options.FindExtension<NamingConventionsOptionsExtension>().NamingConvention;
|
||||
|
||||
if (namingStyle == NamingConvention.None)
|
||||
return conventionSet;
|
||||
|
||||
var nameRewriter = namingStyle switch
|
||||
{
|
||||
NamingConvention.SnakeCase => new SnakeCaseNameRewriter(),
|
||||
_ => throw new NotImplementedException("Unhandled enum value: " + namingStyle)
|
||||
};
|
||||
|
||||
conventionSet.EntityTypeAddedConventions.Add(nameRewriter);
|
||||
conventionSet.PropertyAddedConventions.Add(nameRewriter);
|
||||
return conventionSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace EFCore.NamingConventions.Internal
|
||||
{
|
||||
public class NamingConventionsOptionsExtension : IDbContextOptionsExtension
|
||||
{
|
||||
DbContextOptionsExtensionInfo _info;
|
||||
NamingConvention _namingConvention;
|
||||
|
||||
public NamingConventionsOptionsExtension() {}
|
||||
|
||||
protected NamingConventionsOptionsExtension([NotNull] NamingConventionsOptionsExtension copyFrom)
|
||||
=> _namingConvention = copyFrom._namingConvention;
|
||||
|
||||
public virtual DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this);
|
||||
|
||||
protected virtual NamingConventionsOptionsExtension Clone() => new NamingConventionsOptionsExtension(this);
|
||||
|
||||
internal virtual NamingConvention NamingConvention => _namingConvention;
|
||||
|
||||
public virtual NamingConventionsOptionsExtension WithoutNaming()
|
||||
{
|
||||
var clone = Clone();
|
||||
clone._namingConvention = NamingConvention.None;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public virtual NamingConventionsOptionsExtension WithSnakeCaseNaming()
|
||||
{
|
||||
var clone = Clone();
|
||||
clone._namingConvention = NamingConvention.SnakeCase;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public void Validate(IDbContextOptions options) {}
|
||||
|
||||
public void ApplyServices(IServiceCollection services)
|
||||
=> services.AddEntityFrameworkNamingConventions();
|
||||
|
||||
sealed class ExtensionInfo : DbContextOptionsExtensionInfo
|
||||
{
|
||||
string _logFragment;
|
||||
|
||||
public ExtensionInfo(IDbContextOptionsExtension extension) : base(extension) {}
|
||||
|
||||
new NamingConventionsOptionsExtension Extension
|
||||
=> (NamingConventionsOptionsExtension)base.Extension;
|
||||
|
||||
public override bool IsDatabaseProvider => false;
|
||||
|
||||
public override string LogFragment
|
||||
=> _logFragment ??= Extension._namingConvention switch
|
||||
{
|
||||
NamingConvention.SnakeCase => "using snake-case naming ",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
public override long GetServiceProviderHashCode() => Extension._namingConvention.GetHashCode();
|
||||
|
||||
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
|
||||
=> debugInfo["Naming:" + nameof(NamingConventionsExtensions.UseSnakeCaseNamingConventions)]
|
||||
= Extension._namingConvention.GetHashCode().ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||
|
||||
namespace EFCore.NamingConventions.Internal
|
||||
{
|
||||
class SnakeCaseNameRewriter : IEntityTypeAddedConvention, IPropertyAddedConvention
|
||||
{
|
||||
public void ProcessEntityTypeAdded(
|
||||
IConventionEntityTypeBuilder entityTypeBuilder,
|
||||
IConventionContext<IConventionEntityTypeBuilder> context)
|
||||
=> entityTypeBuilder.ToTable(
|
||||
ConvertToSnakeCase(entityTypeBuilder.Metadata.GetTableName()),
|
||||
entityTypeBuilder.Metadata.GetSchema());
|
||||
|
||||
public void ProcessPropertyAdded(
|
||||
IConventionPropertyBuilder propertyBuilder,
|
||||
IConventionContext<IConventionPropertyBuilder> context)
|
||||
=> propertyBuilder.HasColumnName(
|
||||
ConvertToSnakeCase(propertyBuilder.Metadata.GetColumnName()));
|
||||
|
||||
static string ConvertToSnakeCase(string value)
|
||||
{
|
||||
const char underscore = '_';
|
||||
const UnicodeCategory noneCategory = UnicodeCategory.Control;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
var previousCategory = noneCategory;
|
||||
|
||||
for (var currentIndex = 0; currentIndex < value.Length; currentIndex++)
|
||||
{
|
||||
var currentChar = value[currentIndex];
|
||||
if (currentChar == underscore)
|
||||
{
|
||||
builder.Append(underscore);
|
||||
previousCategory = noneCategory;
|
||||
continue;
|
||||
}
|
||||
|
||||
var currentCategory = char.GetUnicodeCategory(currentChar);
|
||||
switch (currentCategory)
|
||||
{
|
||||
case UnicodeCategory.UppercaseLetter:
|
||||
case UnicodeCategory.TitlecaseLetter:
|
||||
if (previousCategory == UnicodeCategory.SpaceSeparator ||
|
||||
previousCategory == UnicodeCategory.LowercaseLetter ||
|
||||
previousCategory != UnicodeCategory.DecimalDigitNumber &&
|
||||
currentIndex > 0 &&
|
||||
currentIndex + 1 < value.Length &&
|
||||
char.IsLower(value[currentIndex + 1]))
|
||||
{
|
||||
builder.Append(underscore);
|
||||
}
|
||||
|
||||
currentChar = char.ToLower(currentChar);
|
||||
break;
|
||||
|
||||
case UnicodeCategory.LowercaseLetter:
|
||||
case UnicodeCategory.DecimalDigitNumber:
|
||||
if (previousCategory == UnicodeCategory.SpaceSeparator)
|
||||
builder.Append(underscore);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (previousCategory != noneCategory)
|
||||
previousCategory = UnicodeCategory.SpaceSeparator;
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append(currentChar);
|
||||
previousCategory = currentCategory;
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
EFCore.NamingConventions/NamingConventionsExtensions.cs
Normal file
26
EFCore.NamingConventions/NamingConventionsExtensions.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using JetBrains.Annotations;
|
||||
using EFCore.NamingConventions.Internal;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.EntityFrameworkCore
|
||||
{
|
||||
public static class NamingConventionsExtensions
|
||||
{
|
||||
public static DbContextOptionsBuilder UseSnakeCaseNamingConventions([NotNull] this DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
|
||||
|
||||
var extension = (optionsBuilder.Options.FindExtension<NamingConventionsOptionsExtension>() ?? new NamingConventionsOptionsExtension())
|
||||
.WithSnakeCaseNaming();
|
||||
|
||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||
|
||||
return optionsBuilder;
|
||||
}
|
||||
|
||||
public static DbContextOptionsBuilder<TContext> UseSnakeCaseNamingConventions<TContext>([NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder)
|
||||
where TContext : DbContext
|
||||
=> (DbContextOptionsBuilder<TContext>)UseSnakeCaseNamingConventions((DbContextOptionsBuilder)optionsBuilder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
||||
using EFCore.NamingConventions.Internal;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
|
||||
/// </summary>
|
||||
public static class NamingConventionsServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Adds the services required for proxy support in Entity Framework. 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)
|
||||
.TryAdd<IConventionSetPlugin, NamingConventionSetPlugin>();
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
||||
201
LICENSE.txt
Normal file
201
LICENSE.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Naming Conventions for Entity Framework Core Tables and Columns
|
||||
|
||||
By default, EF Core will map to tables and columns named exactly after your .NET classes and properties. For example, mapping a typical Customer class to PostgreSQL will result in SQL such as the following:
|
||||
|
||||
```sql
|
||||
CREATE TABLE "Customers" (
|
||||
"Id" integer NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"FullName" text NULL,
|
||||
CONSTRAINT "PK_Customers" PRIMARY KEY ("Id")
|
||||
);
|
||||
|
||||
SELECT c."Id", c."FullName"
|
||||
FROM "Customers" AS c
|
||||
WHERE c."FullName" = 'John Doe';
|
||||
```
|
||||
|
||||
For PostgreSQL specifically, this forces double-quotes to be added since unquoted identifiers are automatically converted to lower-case - and all those quotes are an eye-sore. But even if we're using another database such as SQL Server, maybe we just hate seeing upper-case letters in our database, and would rather have another naming convention.
|
||||
|
||||
Down with same-name identifier tyranny! Simply add a reference to [EFCore.NamingConventions](https://www.nuget.org/packages/EFCore.NamingConventions/1.0.0-rc1) and enable a naming convention in your model's `OnConfiguring` method:
|
||||
|
||||
```c#
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder
|
||||
.UseNpgsql(...)
|
||||
.UseSnakeCaseNamingConventions();
|
||||
```
|
||||
|
||||
This will automatically make all your table and column names have snake_case naming:
|
||||
|
||||
```sql
|
||||
CREATE TABLE customers (
|
||||
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
full_name text NULL,
|
||||
CONSTRAINT "PK_customers" PRIMARY KEY (id);
|
||||
|
||||
SELECT c.id, c.full_name
|
||||
FROM customers AS c
|
||||
WHERE c.full_name = 'John Doe';
|
||||
```
|
||||
|
||||
Currently, only snake_case is supported, but we can add more conventions as people request them.
|
||||
|
||||
Some important notes:
|
||||
|
||||
* If you have an existing database, adding this naming convention will cause a migration to produced, renaming everything. Be very cautious when doing this (the process currently involves dropping and recreating primary keys).
|
||||
* This plugin will work with any database provider and isn't related to PostgreSQL or Npgsql in any way.
|
||||
* This is a community-maintained plugin: it isn't an official part of Entity Framework Core and isn't supported by Microsoft in any way.
|
||||
5
global.json
Normal file
5
global.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "3.0.100-preview9-014004"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user