AliReza Sabouri
AliReza Sabouri

Reputation: 5215

change entity framework core code first migration name format

ef core using system calendar format for generating migration names.

example of standard migration name for the Gregorian calendar on windows:

20190206144020_MIGRATION-NAME

But if the date format of Windows is something other than the Gregorian, like Persian calendar the ef core migration name generates something like :

13971114210223_MIGRATION-NAME

in a team project, we cannot use both formats because it's changing the order of migrations.

is there any way to fix that issue without changing windows calendar format or manually rename the migration?

version: EF core 2.2

Upvotes: 4

Views: 2253

Answers (3)

Majid Shahabfar
Majid Shahabfar

Reputation: 4829

I usually use the command prompt file or batch file (.cmd) to create a name automatically (including date and time). Doing so I just need to double-click the .cmd file and the migration with my own automatic file name will be performed. here is my .cmd file content (for example add_migrations_Identity.cmd):

For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%a_%%b)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME: =0%") do (set mytime=%%a%%b)
dotnet ef --startup-project MyProject migrations add Identity_V%mydate%_%mytime% -o Migrations/Identity -c IdentityContext
pause

and here my update .cmd file (as an example update_db_Identity.cmd):

dotnet ef --startup-project MyProject database update -c IdentityContext
pause

Upvotes: 0

Ahmadali Shafiee
Ahmadali Shafiee

Reputation: 4657

I've extended the accepted answer and created a class derived from the MigrationsIdGenerator class overriding only the GenerateId method:

public class FixedMigrationsIdGenerator : MigrationsIdGenerator
{
    private const string Format = "yyyyMMddHHmmss";

    private DateTime _lastTimestamp = DateTime.MinValue;
    private readonly object _lock = new object();

    public override string GenerateId(string name)
    {
        var now = DateTime.UtcNow;
        var timestamp = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);

        lock (_lock)
        {
            if (timestamp <= _lastTimestamp)
            {
                timestamp = _lastTimestamp.AddSeconds(1);
            }

            _lastTimestamp = timestamp;
        }

        return timestamp.ToString(Format, CultureInfo.InvariantCulture) + "_" + name;
    }
}

Upvotes: 4

Ivan Stoev
Ivan Stoev

Reputation: 205619

This is simply a bug in the MigrationsIdGenerator class for the latest at this time EF Core 2.2.4 - in the last line of GenerateId method:

return timestamp.ToString(Format) + "_" + name;

they simply forgot to pass CultureInfo.InvariantCulture to DateTime.Format method.

It's already fixed in the current code (I believe for EF Core 3.0), so you either wait for it, or copy/paste the current code to your project (rename the class to let say FixedMigrationsIdGenerator) and then inside your DbContext derived class, override OnConfiguring and add the following (with the necessary usings):

optionsBuilder.ReplaceService<IMigrationsIdGenerator, FixedMigrationsIdGenerator>();

Upvotes: 7

Related Questions