We have recently upgraded our project to Microsoft.EntityFrameworkCore 6.0.0
. This release enables SQL Server temporal tables out of the box.
We have used temporal tables since Entity Framework Core 3.1 using custom migrations as described here:
https://mcmap.net/q/139112/-audit-trail-with-entity-framework-core
Simply following Microsofts guide will of course not work since default column names are PeriodStart
and PeriodEnd
instead of our SysStartTime
and SysEndTime
. History table name does not match either.
modelBuilder
.Entity<Comment>()
.ToTable("Comments", b => b.IsTemporal());
Migration created:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterTable(
name: "Comments")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "CommentsHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AddColumn<DateTime>(
name: "PeriodEnd",
table: "Comments",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AddColumn<DateTime>(
name: "PeriodStart",
table: "Comments",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
}
Creating a custom conversion should fix this as described below:
modelBuilder
.Entity<Comment>()
.ToTable("Comments", tb => tb.IsTemporal(temp =>
{
temp.UseHistoryTable("Comments", "History");
temp.HasPeriodStart("SysStartTime");
temp.HasPeriodEnd("SysEndTime");
}));
However when doing it like this I get the following error on Add-Migration
command:
Period property 'Comment.SysStartTime' must be a shadow property.
To verify there was nothing wrong with any other code I had I reverted to:
modelBuilder
.Entity<Comment>()
.ToTable("Comments", b => b.IsTemporal());
And then added public DateTime PeriodStart { get; set; }
to Comment
.
I then received the error:
Period property 'Comment.PeriodStart' must be a shadow property.
Is there any way to get around this? We use our SysStartTime
as a last modified/last updated value and it works really well. Having to include it via EF.Property<DateTime>(comment, "SysStartTime"))
seems very unnecessary since the column is present both in temporal table and the original table.