Can I add a column Time to the table __EFMigrationsHistory with a utc time of the created row populated.
As I can see at the moment there is a hard-coded HistoryRow which cannot be changed outside.
Any ideas are very welcome.
See the following example
```C#
public class CustomHistoryRepository : NpgsqlHistoryRepository
{
public CustomHistoryRepository(HistoryRepositoryDependencies dependencies)
: base(dependencies)
{
}
protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
{
base.ConfigureTable(history);
history
.Property<DateTime>("Time")
.HasValueGenerator<DateTimeUtcValueGenerator>()
.ValueGeneratedOnAdd();
}
public override string GetInsertScript(HistoryRow row)
{
return base.GetInsertScript(row);
}
}
```C#
var dbOptions = new DbContextOptionsBuilder(options)
.UseNpgsql(settings.DefaultConnection)
.ReplaceService<IHistoryRepository, CustomHistoryRepository>()
.Options;
EF Core version: Microsoft.AspNetCore.Identity.EntityFrameworkCore v.2.1.3
Database Provider: Npgsql.EntityFrameworkCore.PostgreSQL v.2.1.2
Operating system: Visual Studio 2017 Community v.15.8.7
@bricelam to respond
The entity type is currently only used for generating the CREATE TABLE statement. All other configuration is ignored.
You could generate the value in the database using a default value:
history
.Property<DateTime>("Time")
.HasDefaultValueSql("CURRENT_TIMESTAMP AT TIME ZONE 'UTC'");
Or you could manually change the INSERT statement. Note however, that this would do funny things when generating a SQL script form the migrations. The value would be the time you generated the script, not the time you actually applied the migration.
public override string GetInsertScript(HistoryRow row)
{
var stringMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));
var dateTimeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(DateTime));
return @"INSERT INTO ")
.Append(SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema))
.Append(" (")
.Append(SqlGenerationHelper.DelimitIdentifier(MigrationIdColumnName))
.Append(", ")
.Append(SqlGenerationHelper.DelimitIdentifier(ProductVersionColumnName))
.Append(", ")
.Append(SqlGenerationHelper.DelimitIdentifier("Time"))
.AppendLine(")")
.Append("VALUES (")
.Append(stringMapping.GenerateSqlLiteral(row.MigrationId))
.Append(", ")
.Append(stringMapping.GenerateSqlLiteral(row.ProductVersion))
.Append(", ")
.Append(dateTimeMapping.GenerateSqlLiteral(DateTime.UtcNow))
.Append(")")
.AppendLine(SqlGenerationHelper.StatementTerminator)
.ToString();
}
Your code may also just work after we implement #2737.
Thanks Brice. Your solution with HasDefaultValueSql works fine. Did't know about HasDefaultValueSql as it was different namespace I had to add.
Most helpful comment
The entity type is currently only used for generating the
CREATE TABLEstatement. All other configuration is ignored.You could generate the value in the database using a default value:
Or you could manually change the INSERT statement. Note however, that this would do funny things when generating a SQL script form the migrations. The value would be the time you generated the script, not the time you actually applied the migration.