Skip to content

Allow temporal period properties to be mapped to CLR properties#38110

Merged
roji merged 4 commits intomainfrom
roji/temporal-period-clr-properties
Apr 15, 2026
Merged

Allow temporal period properties to be mapped to CLR properties#38110
roji merged 4 commits intomainfrom
roji/temporal-period-clr-properties

Conversation

@roji
Copy link
Copy Markdown
Member

@roji roji commented Apr 15, 2026

Fixes #26463

Summary

Temporal period properties (PeriodStart/PeriodEnd) were previously required to be shadow properties. This PR removes that restriction, allowing them to be mapped to CLR properties on the entity type.

Changes

Product code

  • Removed shadow-property validation in SqlServerModelValidator — the IsShadowProperty() check on period properties is no longer enforced.
  • Added lambda-based HasPeriodStart/HasPeriodEnd overloads on TemporalTableBuilder<TEntity> and OwnedNavigationTemporalTableBuilder<TOwner, TDependentEntity> for strongly-typed configuration:
    entity.ToTable(tb => tb.IsTemporal(ttb =>
    {
        ttb.HasPeriodStart(e => e.PeriodStart);
        ttb.HasPeriodEnd(e => e.PeriodEnd);
    }));

Scaffolding

No change — period columns are still excluded from the scaffolding column query and generated as shadow properties by default.

Why it just works

  • SqlServerTemporalConvention already discovers existing CLR properties via entityTypeBuilder.Property(typeof(DateTime), periodPropertyName).
  • Period properties are configured with ValueGenerated.OnAddOrUpdate, which sets BeforeSaveBehavior to Ignore — so they're automatically excluded from INSERT/UPDATE even as CLR properties.

Tests

  • Updated validator test to expect success for CLR period properties
  • Added model building tests (string-based and lambda-based CLR period configuration)
  • Updated scaffolding round-trip test (now succeeds instead of throwing)
  • Added E2E functional tests exercising CLR period properties with temporal queries

Remove the shadow-property validation enforcement in SqlServerModelValidator,
allowing temporal period properties (PeriodStart/PeriodEnd) to be mapped to
CLR properties instead of requiring them to be shadow properties.

Add lambda-based HasPeriodStart/HasPeriodEnd overloads on
TemporalTableBuilder<TEntity> and
OwnedNavigationTemporalTableBuilder<TOwner, TDependentEntity> for
strongly-typed period property configuration.

Scaffolding behavior is unchanged: period columns are still excluded from the
column query and scaffolded as shadow properties by default.

Fixes #26463

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 15, 2026 12:43
@roji roji requested a review from a team as a code owner April 15, 2026 12:43
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the restriction that SQL Server temporal period properties must be shadow properties, allowing them to be mapped to CLR properties, and adds strongly-typed (lambda) configuration APIs for temporal period properties.

Changes:

  • Removed temporal period “shadow-only” validation from SqlServerModelValidator.
  • Added lambda-based HasPeriodStart/HasPeriodEnd overloads for temporal table builders.
  • Updated/added tests across validator, model building, scaffolding, and functional temporal query scenarios to cover CLR period properties.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/EFCore.SqlServer.Tests/Infrastructure/SqlServerModelValidatorTest.cs Updates validator test to accept CLR-mapped period properties.
test/EFCore.SqlServer.FunctionalTests/Query/TemporalTableSqlServerTest.cs Adds functional coverage for CLR period properties (including temporal queries).
test/EFCore.SqlServer.FunctionalTests/ModelBuilding/SqlServerModelBuilderTestBase.cs Adds model-building tests and test-builder support for lambda-based period configuration.
test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs Updates scaffolding test to validate temporal metadata without expecting a validator exception.
src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs Adds lambda overloads for period start/end configuration on generic temporal builder.
src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder``.cs Adds lambda overloads for period start/end configuration on generic owned-navigation temporal builder.
src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs Removes the check enforcing period properties to be shadow properties.
src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs Updates comment to reflect rev-eng behavior (period properties remain shadow by default).
Files not reviewed (1)
  • src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs: Language not supported

Comment thread src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs Outdated
Comment thread src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder``.cs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 15, 2026 20:45
@roji roji enabled auto-merge (squash) April 15, 2026 20:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs: Language not supported

Comment thread src/EFCore.SqlServer/EFCore.SqlServer.baseline.json
@roji roji merged commit 742d0f9 into main Apr 15, 2026
19 checks passed
@roji roji deleted the roji/temporal-period-clr-properties branch April 15, 2026 22:29
@github-actions github-actions Bot added the api-review This PR or issue is introducing public API changes that need to be reviewed label Apr 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

API review baseline changes for src/EFCore.SqlServer/EFCore.SqlServer.baseline.json

Show diff

The diff below was generated by ApiChief between the base and the PR.

  class Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity> : Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationTemporalTableBuilder where TOwnerEntity : class where TDependentEntity : class
+ virtual OwnedNavigationTemporalPeriodPropertyBuilder OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity>.HasPeriodEnd(Expression<Func<TDependentEntity, DateTime>> propertyExpression);
+ virtual OwnedNavigationTemporalPeriodPropertyBuilder OwnedNavigationTemporalTableBuilder<TOwnerEntity, TDependentEntity>.HasPeriodStart(Expression<Func<TDependentEntity, DateTime>> propertyExpression);
  class Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalTableBuilder<TEntity> : Microsoft.EntityFrameworkCore.Metadata.Builders.TemporalTableBuilder where TEntity : class
+ virtual TemporalPeriodPropertyBuilder TemporalTableBuilder<TEntity>.HasPeriodEnd(Expression<Func<TEntity, DateTime>> propertyExpression);
+ virtual TemporalPeriodPropertyBuilder TemporalTableBuilder<TEntity>.HasPeriodStart(Expression<Func<TEntity, DateTime>> propertyExpression);

roji added a commit to roji/EntityFramework.Docs that referenced this pull request Apr 16, 2026
Document the new EF Core 11 feature that allows temporal period
properties (PeriodStart/PeriodEnd) to be mapped to CLR properties
instead of being restricted to shadow properties.

Updates:
- temporal-tables.md: New 'Mapping period columns to CLR properties'
  section with lambda and string-based configuration examples
- temporal-tables.md: Updated existing text to note shadow properties
  are the default, with links to the new section
- whatsnew.md (EF Core 11): New subsection under SQL Server

Relates to dotnet/efcore#38110

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
roji added a commit to roji/EntityFramework.Docs that referenced this pull request Apr 16, 2026
Document the new EF Core 11 feature that allows temporal period
properties (PeriodStart/PeriodEnd) to be mapped to CLR properties
instead of being restricted to shadow properties.

Updates:
- temporal-tables.md: New 'Mapping period columns to CLR properties'
  section with lambda and string-based configuration examples
- temporal-tables.md: Updated existing text to note shadow properties
  are the default, with links to the new section
- whatsnew.md (EF Core 11): New subsection under SQL Server

Relates to dotnet/efcore#38110

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
roji added a commit to dotnet/EntityFramework.Docs that referenced this pull request Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-review This PR or issue is introducing public API changes that need to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow temporal Period properties to be mapped to CLR properties (i.e. not shadow properties)

3 participants