Entity Framework Core: Naming Convention

 
 
  • Gérald Barré

Note: I use the preview version of Entity Framework Core 2.0 (2.0.0-preview1-final). Things may change in the final release.

Entity Framework migrations generate the database schema from the model, inferring object names from class and property names. The defaults work well for most projects. However, your DBA may require a specific naming convention - for example, uppercase table names or column names prefixed with the table name.

Entity Framework lets you set the name of a table or column individually:

C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().ForSqlServerToTable("Blog");
}

However, doing this object by object is tedious and error-prone. Instead, you can apply names globally by modifying the model. Because modelBuilder is read/write, you can iterate over all objects and rename them.

C#
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Singularize table name
        // Blogs => Blog
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            // Add NuGet package "Humanizer" to use Singularize()
            entityType.Relational().TableName = entityType.Relational().TableName.Singularize();
        }

        // Prefix column names with table name
        // Id => Blog_Id
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityType.GetProperties())
            {
                property.Relational().ColumnName = entityType.Relational().TableName + "_" + property.Relational().ColumnName;
            }
        }

        // Rename Foreign Key
        // FK_Post_Blog_BlogId => FK_Post_Blog_BlogId_Test
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityType.GetProperties())
            {
                foreach (var fk in entityType.FindForeignKeys(property))
                {
                    fk.Relational().Name = fk.Relational().Name + "_Test";
                }
            }
        }

        // Rename Indices
        // IX_Blog_Url => IX_Blog_Url_Test
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var index in entityType.GetIndexes())
            {
                index.Relational().Name = index.Relational().Name + "_Test";
            }
        }
    }
}

Run the following commands in the Package Manager Console:

PowerShell
Add-Migration NamingConvention
Update-Database

The commands above generate the following schema:

SQL
CREATE TABLE [dbo].[Blog] (
    [Blog_BlogId] INT            IDENTITY (1, 1) NOT NULL,
    [Blog_Url]    NVARCHAR (450) NULL,
    CONSTRAINT [PK_Blog] PRIMARY KEY CLUSTERED ([Blog_BlogId] ASC)
);

CREATE UNIQUE NONCLUSTERED INDEX [IX_Blog_Url_Test]
    ON [dbo].[Blog]([Blog_Url] ASC) WHERE ([Blog_Url] IS NOT NULL);

CREATE TABLE [dbo].[Post] (
    [Post_PostId]  INT            IDENTITY (1, 1) NOT NULL,
    [Post_BlogId]  INT            NOT NULL,
    [Post_Content] NVARCHAR (MAX) NULL,
    [Post_Title]   NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_Post] PRIMARY KEY CLUSTERED ([Post_PostId] ASC),
    CONSTRAINT [testFK_Post_Blog_BlogId] FOREIGN KEY ([Post_BlogId]) REFERENCES [dbo].[Blog] ([Blog_BlogId]) ON DELETE CASCADE
);

CREATE NONCLUSTERED INDEX [IX_Post_BlogId_Test]
    ON [dbo].[Post]([Post_BlogId] ASC);

As you can see, the generated database objects follow the naming convention defined above.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?