Entity Framework Core: Naming Convention
Note: I use the preview version of Entity Framework Core 2.0 (2.0.0-preview1-final). Things may change after the final version is released
Entity Framework migration allows generating the database schema from the model. This means the name of generated objects has to be inferred from the name of the classes and properties. The default names should be ok for lots of people. However, your DBA may ask you to use a specific naming convention. For instance, some DBA want the table name to be upper case, or column names to be prefixed by the table name.
Entity Framework allows to set the name of a table or a column one by one:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().ForSqlServerToTable("Blog");
}
However, this code is very boring to write and error-prone. Instead of setting the name object by object, you can set it globally by modifying the model. Indeed, the modelBuilder
is read/write. This means you can iterate all objects and change their names.
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
Add-Migration NamingConvention
Update-Database
The previous commands will generate the following schema:
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 name of the generated database objects follow the naming convention defined.
Do you have a question or a suggestion about this post? Contact me!