From b3619b49eb43fdeb8c93d167f2bc1fd67c2735ec Mon Sep 17 00:00:00 2001 From: maumar Date: Mon, 2 Aug 2021 15:43:10 -0700 Subject: [PATCH] Fix to #25511 - Temporal Tables: The given key 'SqlServer:TemporalHistoryTableName' was not present in the dictionary when creating migration on entity mapped to temporal table without explicitly providing history table name Problem was that we don't store the default history table name in the annotation (like we do with default period property names), instead the getter on IReadOnlyEntityType retrieves the default value if needed. Fix is to check if the history table annotation is present in the annotation list, just like we do with the history table schema. Fixes #25511 --- .../SqlServerAnnotationCodeGenerator.cs | 5 +- .../Migrations/ModelSnapshotSqlServerTest.cs | 56 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs index 6a38b95f1db..43e02397891 100644 --- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs +++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs @@ -189,7 +189,10 @@ public SqlServerAnnotationCodeGenerator(AnnotationCodeGeneratorDependencies depe if (annotations.TryGetValue(SqlServerAnnotationNames.IsTemporal, out var isTemporalAnnotation) && isTemporalAnnotation.Value as bool? == true) { - var historyTableName = annotations[SqlServerAnnotationNames.TemporalHistoryTableName].Value as string; + var historyTableName = annotations.ContainsKey(SqlServerAnnotationNames.TemporalHistoryTableName) + ? annotations[SqlServerAnnotationNames.TemporalHistoryTableName].Value as string + : null; + var historyTableSchema = annotations.ContainsKey(SqlServerAnnotationNames.TemporalHistoryTableSchema) ? annotations[SqlServerAnnotationNames.TemporalHistoryTableSchema].Value as string : null; diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index ad23167c10a..0df68a0fb97 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -1901,6 +1901,62 @@ public virtual void Temporal_table_information_is_stored_in_snapshot() }); } + [ConditionalFact] + public virtual void Temporal_table_information_is_stored_in_snapshot_minimal_setup() + { + Test( + builder => builder.Entity().ToTable(tb => tb.IsTemporal()), + AddBoilerPlate( + GetHeading() + + @" + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty"", b => + { + b.Property(""Id"") + .ValueGeneratedOnAdd() + .HasColumnType(""int""); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property(""Id""), 1L, 1); + + b.Property(""Name"") + .HasColumnType(""nvarchar(max)""); + + b.Property(""PeriodEnd"") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType(""datetime2"") + .HasColumnName(""PeriodEnd""); + + b.Property(""PeriodStart"") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType(""datetime2"") + .HasColumnName(""PeriodStart""); + + b.HasKey(""Id""); + + b.ToTable(""EntityWithStringProperty""); + + b.ToTable(tb => tb.IsTemporal(ttb => + { + ttb + .HasPeriodStart(""PeriodStart"") + .HasColumnName(""PeriodStart""); + ttb + .HasPeriodEnd(""PeriodEnd"") + .HasColumnName(""PeriodEnd""); + } + )); + });", usingSystem: true), + o => + { + var temporalEntity = o.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty"); + var annotations = temporalEntity.GetAnnotations().ToList(); + + Assert.Equal(5, annotations.Count); + Assert.Contains(annotations, a => a.Name == SqlServerAnnotationNames.IsTemporal && a.Value as bool? == true); + Assert.Contains(annotations, a => a.Name == SqlServerAnnotationNames.TemporalPeriodStartPropertyName && a.Value as string == "PeriodStart"); + Assert.Contains(annotations, a => a.Name == SqlServerAnnotationNames.TemporalPeriodEndPropertyName && a.Value as string == "PeriodEnd"); + }); + } + #endregion #region Owned types