Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ private static readonly MethodInfo TemporalPropertyHasColumnNameMethodInfo
= typeof(TemporalPeriodPropertyBuilder).GetRuntimeMethod(
nameof(TemporalPeriodPropertyBuilder.HasColumnName), [typeof(string)])!;

private static readonly MethodInfo TemporalTablePeriodColumnsHiddenMethodInfo
= typeof(TemporalTableBuilder).GetRuntimeMethod(
nameof(TemporalTableBuilder.PeriodColumnsHidden), [typeof(bool)])!;

private static readonly MethodInfo ModelHasFullTextCatalogMethodInfo
= typeof(SqlServerModelBuilderExtensions).GetRuntimeMethod(
nameof(SqlServerModelBuilderExtensions.HasFullTextCatalog), [typeof(ModelBuilder), typeof(string)])!;
Expand Down Expand Up @@ -385,6 +389,14 @@ public override IReadOnlyList<MethodCallCodeFragment> GenerateFluentApiCalls(
.Chain(new MethodCallCodeFragment(TemporalPropertyHasColumnNameMethodInfo, periodEndColumnName))
: new MethodCallCodeFragment(TemporalTableHasPeriodEndMethodInfo, periodEndPropertyName));

// ttb => ttb.PeriodColumnsHidden(false)
// Only emit when explicitly set to false; the default (true) matches legacy behavior.
if (annotations.TryGetValue(SqlServerAnnotationNames.TemporalPeriodColumnsHidden, out var periodColumnsHiddenAnnotation)
&& periodColumnsHiddenAnnotation.Value as bool? == false)
{
temporalTableBuilderCalls.Add(new MethodCallCodeFragment(TemporalTablePeriodColumnsHiddenMethodInfo, false));
}

// ToTable(tb => tb.IsTemporal(ttb => { ... }))
var toTemporalTableCall = new MethodCallCodeFragment(
EntityTypeToTableMethodInfo,
Expand All @@ -403,6 +415,7 @@ public override IReadOnlyList<MethodCallCodeFragment> GenerateFluentApiCalls(
annotations.Remove(SqlServerAnnotationNames.TemporalHistoryTableSchema);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodStartPropertyName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodEndPropertyName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodColumnsHidden);
}

return fragments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public override void Generate(IColumn column, CSharpRuntimeAnnotationCodeGenerat
annotations.Remove(SqlServerAnnotationNames.Sparse);
annotations.Remove(SqlServerAnnotationNames.TemporalIsPeriodStartColumn);
annotations.Remove(SqlServerAnnotationNames.TemporalIsPeriodEndColumn);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodColumnsHidden);
}

base.Generate(column, parameters);
Expand Down Expand Up @@ -171,6 +172,7 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod
annotations.Remove(SqlServerAnnotationNames.TemporalHistoryTableSchema);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodEndPropertyName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodStartPropertyName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodColumnsHidden);
}

base.Generate(entityType, parameters);
Expand All @@ -187,6 +189,7 @@ public override void Generate(ITable table, CSharpRuntimeAnnotationCodeGenerator
annotations.Remove(SqlServerAnnotationNames.TemporalHistoryTableSchema);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodEndColumnName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodStartColumnName);
annotations.Remove(SqlServerAnnotationNames.TemporalPeriodColumnsHidden);
}

base.Generate(table, parameters);
Expand Down
24 changes: 24 additions & 0 deletions src/EFCore.SqlServer/EFCore.SqlServer.baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@
{
"Member": "override string? ToString();"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder PeriodColumnsHidden(bool hidden = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder UseHistoryTable(string name);"
},
Expand All @@ -255,6 +258,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodStart(System.Linq.Expressions.Expression<System.Func<TDependentEntity, System.DateTime>> propertyExpression);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity> PeriodColumnsHidden(bool hidden = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity> UseHistoryTable(string name);"
},
Expand Down Expand Up @@ -1122,6 +1128,9 @@
{
"Member": "static Microsoft.EntityFrameworkCore.Metadata.ConfigurationSource? GetIsTemporalConfigurationSource(this Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType entityType);"
},
{
"Member": "static Microsoft.EntityFrameworkCore.Metadata.ConfigurationSource? GetIsTemporalPeriodColumnsHiddenConfigurationSource(this Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType entityType);"
},
{
"Member": "static string? GetPeriodEndPropertyName(this Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType entityType);"
},
Expand Down Expand Up @@ -1155,6 +1164,9 @@
{
"Member": "static bool IsTemporal(this Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType entityType);"
},
{
"Member": "static bool IsTemporalPeriodColumnsHidden(this Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType entityType);"
},
{
"Member": "static void SetHistoryTableName(this Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType entityType, string? historyTableName);"
},
Expand All @@ -1179,6 +1191,12 @@
{
"Member": "static bool? SetIsTemporal(this Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType entityType, bool? temporal, bool fromDataAnnotation = false);"
},
{
"Member": "static void SetIsTemporalPeriodColumnsHidden(this Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType entityType, bool? hidden);"
},
{
"Member": "static bool? SetIsTemporalPeriodColumnsHidden(this Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType entityType, bool? hidden, bool fromDataAnnotation = false);"
},
{
"Member": "static void SetPeriodEndPropertyName(this Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType entityType, string? periodEndPropertyName);"
},
Expand Down Expand Up @@ -3049,6 +3067,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalPeriodPropertyBuilder HasPeriodStart(string propertyName);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalTableBuilder PeriodColumnsHidden(bool hidden = true);"
},
{
"Member": "override string? ToString();"
},
Expand All @@ -3069,6 +3090,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalPeriodPropertyBuilder HasPeriodStart(System.Linq.Expressions.Expression<System.Func<TEntity, System.DateTime>> propertyExpression);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalTableBuilder<TEntity> PeriodColumnsHidden(bool hidden = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalTableBuilder<TEntity> UseHistoryTable(string name);"
},
Expand Down
47 changes: 47 additions & 0 deletions src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,53 @@ public static void SetHistoryTableSchema(this IMutableEntityType entityType, str
return (string.IsNullOrEmpty(schema) ? "" : schema + ".") + historyTableName;
}

/// <summary>
/// Returns a value indicating whether the period columns of the entity type mapped to a temporal table are
/// defined with the HIDDEN flag, which excludes them from <c>SELECT *</c> results.
/// </summary>
/// <remarks>
/// The default value is <see langword="true" />, matching the behavior of EF Core releases prior to this option
/// being introduced. Set to <see langword="false" /> to make the period columns visible.
/// </remarks>
/// <param name="entityType">The entity type.</param>
/// <returns><see langword="true" /> if the period columns are hidden; otherwise <see langword="false" />.</returns>
public static bool IsTemporalPeriodColumnsHidden(this IReadOnlyEntityType entityType)
=> entityType[SqlServerAnnotationNames.TemporalPeriodColumnsHidden] as bool? ?? true;

/// <summary>
/// Sets a value indicating whether the period columns of the entity type mapped to a temporal table are
/// defined with the HIDDEN flag.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="hidden">The value to set; <see langword="null" /> to remove the explicit configuration.</param>
public static void SetIsTemporalPeriodColumnsHidden(this IMutableEntityType entityType, bool? hidden)
=> entityType.SetOrRemoveAnnotation(SqlServerAnnotationNames.TemporalPeriodColumnsHidden, hidden);

/// <summary>
/// Sets a value indicating whether the period columns of the entity type mapped to a temporal table are
/// defined with the HIDDEN flag.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="hidden">The value to set; <see langword="null" /> to remove the explicit configuration.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static bool? SetIsTemporalPeriodColumnsHidden(
this IConventionEntityType entityType,
bool? hidden,
bool fromDataAnnotation = false)
=> (bool?)entityType.SetOrRemoveAnnotation(
SqlServerAnnotationNames.TemporalPeriodColumnsHidden,
hidden,
fromDataAnnotation)?.Value;

/// <summary>
/// Gets the configuration source for the period-columns-hidden setting.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns>The configuration source for the period-columns-hidden setting.</returns>
public static ConfigurationSource? GetIsTemporalPeriodColumnsHiddenConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(SqlServerAnnotationNames.TemporalPeriodColumnsHidden)?.GetConfigurationSource();

#endregion Temporal table

#region SQL OUTPUT clause
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodEnd(string
#pragma warning restore EF1001 // Internal EF Core API usage.
}

/// <summary>
/// Configures whether the period columns of the temporal table are defined with the HIDDEN flag,
/// which excludes them from <c>SELECT *</c> results.
/// </summary>
/// <remarks>
/// <para>
/// The default value is <see langword="true" />, matching the behavior of EF Core releases prior to this option
/// being introduced. Set to <see langword="false" /> to make the period columns visible in <c>SELECT *</c>.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-temporal">Using SQL Server temporal tables with EF Core</see>
/// for more information.
/// </para>
/// </remarks>
/// <param name="hidden">A value indicating whether the period columns should be hidden.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public virtual OwnedNavigationTemporalTableBuilder PeriodColumnsHidden(bool hidden = true)
{
_referenceOwnershipBuilder.OwnedEntityType.SetIsTemporalPeriodColumnsHidden(hidden);

return this;
}

private IMutableProperty ConfigurePeriodProperty(string propertyName)
{
// TODO: Configure the property explicitly, but remove it if it's no longer used, issue #15898
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,23 @@ public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodStart(
public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodEnd(
Expression<Func<TDependentEntity, DateTime>> propertyExpression)
=> HasPeriodEnd(Check.NotNull(propertyExpression).GetMemberAccess().Name);

/// <summary>
/// Configures whether the period columns of the temporal table are defined with the HIDDEN flag,
/// which excludes them from <c>SELECT *</c> results.
/// </summary>
/// <remarks>
/// <para>
/// The default value is <see langword="true" />, matching the behavior of EF Core releases prior to this option
/// being introduced. Set to <see langword="false" /> to make the period columns visible in <c>SELECT *</c>.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-temporal">Using SQL Server temporal tables with EF Core</see>
/// for more information.
/// </para>
/// </remarks>
/// <param name="hidden">A value indicating whether the period columns should be hidden.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public new virtual OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity> PeriodColumnsHidden(bool hidden = true)
=> (OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity>)base.PeriodColumnsHidden(hidden);
}
23 changes: 23 additions & 0 deletions src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ public virtual TemporalPeriodPropertyBuilder HasPeriodEnd(string propertyName)
#pragma warning restore EF1001 // Internal EF Core API usage.
}

/// <summary>
/// Configures whether the period columns of the temporal table are defined with the HIDDEN flag,
/// which excludes them from <c>SELECT *</c> results.
/// </summary>
/// <remarks>
/// <para>
/// The default value is <see langword="true" />, matching the behavior of EF Core releases prior to this option
/// being introduced. Set to <see langword="false" /> to make the period columns visible in <c>SELECT *</c>.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-temporal">Using SQL Server temporal tables with EF Core</see>
/// for more information and examples.
/// </para>
/// </remarks>
/// <param name="hidden">A value indicating whether the period columns should be hidden.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public virtual TemporalTableBuilder PeriodColumnsHidden(bool hidden = true)
{
_entityTypeBuilder.Metadata.SetIsTemporalPeriodColumnsHidden(hidden);

return this;
}

private IMutableProperty ConfigurePeriodProperty(string propertyName)
{
// TODO: Configure the property explicitly, but remove it if it's no longer used, issue #15898
Expand Down
19 changes: 19 additions & 0 deletions src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,23 @@ public virtual TemporalPeriodPropertyBuilder HasPeriodStart(Expression<Func<TEnt
/// <returns>An object that can be used to configure the period end property.</returns>
public virtual TemporalPeriodPropertyBuilder HasPeriodEnd(Expression<Func<TEntity, DateTime>> propertyExpression)
=> HasPeriodEnd(Check.NotNull(propertyExpression).GetMemberAccess().Name);

/// <summary>
/// Configures whether the period columns of the temporal table are defined with the HIDDEN flag,
/// which excludes them from <c>SELECT *</c> results.
/// </summary>
/// <remarks>
/// <para>
/// The default value is <see langword="true" />, matching the behavior of EF Core releases prior to this option
/// being introduced. Set to <see langword="false" /> to make the period columns visible in <c>SELECT *</c>.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-temporal">Using SQL Server temporal tables with EF Core</see>
/// for more information and examples.
/// </para>
/// </remarks>
/// <param name="hidden">A value indicating whether the period columns should be hidden.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public new virtual TemporalTableBuilder<TEntity> PeriodColumnsHidden(bool hidden = true)
=> (TemporalTableBuilder<TEntity>)base.PeriodColumnsHidden(hidden);
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ public static class SqlServerAnnotationNames
/// </summary>
public const string TemporalIsPeriodEndColumn = Prefix + "TemporalIsPeriodEndColumn";

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public const string TemporalPeriodColumnsHidden = Prefix + "TemporalPeriodColumnsHidden";

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ public override IEnumerable<IAnnotation> For(ITable table, bool designTime)

yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodEndColumnName, periodEndColumnName);
}

if (!entityType.IsTemporalPeriodColumnsHidden())
{
yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodColumnsHidden, false);
}
}
}

Expand Down Expand Up @@ -351,10 +356,20 @@ public override IEnumerable<IAnnotation> For(IColumn column, bool designTime)
if (column.Name == periodStartColumnName)
{
yield return new Annotation(SqlServerAnnotationNames.TemporalIsPeriodStartColumn, true);

if (!entityType.IsTemporalPeriodColumnsHidden())
{
yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodColumnsHidden, false);
}
}
else if (column.Name == periodEndColumnName)
{
yield return new Annotation(SqlServerAnnotationNames.TemporalIsPeriodEndColumn, true);

if (!entityType.IsTemporalPeriodColumnsHidden())
{
yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodColumnsHidden, false);
}
}
}
}
Expand Down
Loading
Loading