/efcore-snakecase

Map Entity's name from CamelCase to SQL snake_case for migrations (on any database)

Primary LanguageC#MIT LicenseMIT

Marques.EFCore.SnakeCase Extensions

v2 Build status v3 Build status v6 Build status

This is an Entity Framework Core extension method to SnakeCase all structures of your DbContext.

  • It is database agnostic (EFCore)
  • NetStandard 2.0 (for core 2.x)
  • NetStandard 2.1 (for core 3.0)
  • net6.0 (for core 6.x.x)

Enougth talking:

Getting Started

  1. Install Package according to your .net flavor
// For .net core 2.x CLI 
> dotnet add package Marques.EFCore.SnakeCase 
// For .net core 3.0 - 5.0
> dotnet add package Marques.EFCorev3.0.SnakeCase
// For .net core 6.0
> dotnet add package Marques.EFCorev6.0.SnakeCase


// Or from Visual Studio Packge Manager for 2.x
 Install-Package Marques.EFCore.SnakeCase
 // for .net core 3 - 5
 Install-Package Marques.EFCorev3.0.SnakeCase
 // for .net 6
 Install-Package Marques.EFCorev6.0.SnakeCase
  1. Then on your DbContext
//... cut for simplicity
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // This is the only line you need to add in your context
    modelBuilder.ToSnakeCase();
}

The full DbContext can be found at sample/SampleConsoleApp/Data/SampleDbContex.cs

  1. Run migration scripts like you are used to.

Here I'll generate them:

> dotnet ef migrations add "initial"
> dotnet ef migrations script

Entities and DbContext used:

// Source model in CamelCase notation
public class SampleDbContext: DbContext {
    public DbSet<Person> People { get; set; }
    public DbSet<PersonalObject> Belongings { get; set; }
    // ...
}

public class Person
{
    public int PersonId { get; set; }
    public string PersonalEmail { get; set; }
    public int AverageRate { get; set; }
    public List<PersonalObject> Belongings { get; set; }
}

public class PersonalObject
{
    public int PersonalObjectId { get; set; }
    public string PersonalObjectTitle { get; set; }
    public string PersonalObjectContent { get; set; }

    public int PersonId { get; set; }
    public Person Owner { get; set; }
}

After waiting for the steps above here is the result.

--  SQLite script generated by ef migrations
CREATE TABLE "people" (
    "person_id" INTEGER NOT NULL CONSTRAINT "pk_people" PRIMARY KEY AUTOINCREMENT,
    "personal_email" TEXT NULL,
    "average_rate" INTEGER NOT NULL
);

CREATE TABLE "belongings" (
    "personal_object_id" INTEGER NOT NULL CONSTRAINT "pk_belongings" PRIMARY KEY AUTOINCREMENT,
    "personal_object_title" TEXT NULL,
    "personal_object_content" TEXT NULL,
    "person_id" INTEGER NOT NULL,
    CONSTRAINT "fk_belongings_people_person_id" FOREIGN KEY ("person_id")
    REFERENCES "people" ("person_id") ON DELETE CASCADE
);

CREATE INDEX "ix_belongings_person_id" ON "belongings" ("person_id");

Considerations

  1. This extension is Database provider agnostic, should work with every EFCore provider, in my case it was battle tested with PostgreSQL with no problems.
  2. The __EFHistoryMigration table can follow the same pattern but needs extra implementation for each provider (SQLite, SQLServer, MySQL, etc.)

License

MIT

Pull requests are welcome