Skip to content

Commit c173a6b

Browse files
committed
Temporal table support for owned and table splitting scenarios
Fix to #26858 - Query: improve TableExpressionBase extensibility by adding annotations Fix to #26469 - Query: enable temporal tables for table splitting scenarios Fix to #26451 - Temporal Table: Owned Entities support? Added annotation infra for TableExpressionBase and annotations for temporal table information. Removed (now unnecessary) temporal specific table expressions. Also added temporal table support for owned typed and table splitting in general using the annotations to store the temporal information (no need for provider specific logic in places where we didn't have good extensibility) For table splitting, every entity must explicitly define period start/end columns. They all need to be the same, but if not explicitly provided we try to uniquefy them. We should fix this so that you only need to specify it in one place but it's currently hard to do (hopefully convention layering will make it easier) Fixes #26858 Fixes #26469 Fixes #26451
1 parent fe1f86d commit c173a6b

File tree

52 files changed

+7535
-537
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+7535
-537
lines changed

src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs

+18-18
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static EntityTypeBuilder ToTable(
5151
{
5252
Check.NotNull(buildAction, nameof(buildAction));
5353

54-
buildAction(new TableBuilder(null, null, entityTypeBuilder.Metadata));
54+
buildAction(new TableBuilder(null, null, entityTypeBuilder));
5555

5656
return entityTypeBuilder;
5757
}
@@ -76,7 +76,7 @@ public static EntityTypeBuilder ToTable(
7676

7777
entityTypeBuilder.Metadata.SetTableName(name);
7878
entityTypeBuilder.Metadata.SetSchema(null);
79-
buildAction(new TableBuilder(name, null, entityTypeBuilder.Metadata));
79+
buildAction(new TableBuilder(name, null, entityTypeBuilder));
8080

8181
return entityTypeBuilder;
8282
}
@@ -114,7 +114,7 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
114114
{
115115
Check.NotNull(buildAction, nameof(buildAction));
116116

117-
buildAction(new TableBuilder<TEntity>(null, null, entityTypeBuilder.Metadata));
117+
buildAction(new TableBuilder<TEntity>(null, null, entityTypeBuilder));
118118

119119
return entityTypeBuilder;
120120
}
@@ -141,7 +141,7 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
141141

142142
entityTypeBuilder.Metadata.SetTableName(name);
143143
entityTypeBuilder.Metadata.SetSchema(null);
144-
buildAction(new TableBuilder<TEntity>(name, null, entityTypeBuilder.Metadata));
144+
buildAction(new TableBuilder<TEntity>(name, null, entityTypeBuilder));
145145

146146
return entityTypeBuilder;
147147
}
@@ -192,7 +192,7 @@ public static EntityTypeBuilder ToTable(
192192

193193
entityTypeBuilder.Metadata.SetTableName(name);
194194
entityTypeBuilder.Metadata.SetSchema(schema);
195-
buildAction(new TableBuilder(name, schema, entityTypeBuilder.Metadata));
195+
buildAction(new TableBuilder(name, schema, entityTypeBuilder));
196196

197197
return entityTypeBuilder;
198198
}
@@ -240,7 +240,7 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
240240

241241
entityTypeBuilder.Metadata.SetTableName(name);
242242
entityTypeBuilder.Metadata.SetSchema(schema);
243-
buildAction(new TableBuilder<TEntity>(name, schema, entityTypeBuilder.Metadata));
243+
buildAction(new TableBuilder<TEntity>(name, schema, entityTypeBuilder));
244244

245245
return entityTypeBuilder;
246246
}
@@ -277,11 +277,11 @@ public static OwnedNavigationBuilder ToTable(
277277
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
278278
public static OwnedNavigationBuilder ToTable(
279279
this OwnedNavigationBuilder referenceOwnershipBuilder,
280-
Action<TableBuilder> buildAction)
280+
Action<OwnedNavigationTableBuilder> buildAction)
281281
{
282282
Check.NotNull(buildAction, nameof(buildAction));
283283

284-
buildAction(new TableBuilder(null, null, referenceOwnershipBuilder.OwnedEntityType));
284+
buildAction(new OwnedNavigationTableBuilder(null, null, referenceOwnershipBuilder));
285285

286286
return referenceOwnershipBuilder;
287287
}
@@ -297,13 +297,13 @@ public static OwnedNavigationBuilder ToTable(
297297
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
298298
public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwnerEntity, TRelatedEntity>(
299299
this OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> referenceOwnershipBuilder,
300-
Action<TableBuilder<TRelatedEntity>> buildAction)
300+
Action<OwnedNavigationTableBuilder<TRelatedEntity>> buildAction)
301301
where TOwnerEntity : class
302302
where TRelatedEntity : class
303303
{
304304
Check.NotNull(buildAction, nameof(buildAction));
305305

306-
buildAction(new TableBuilder<TRelatedEntity>(null, null, referenceOwnershipBuilder.OwnedEntityType));
306+
buildAction(new OwnedNavigationTableBuilder<TRelatedEntity>(null, null, referenceOwnershipBuilder));
307307

308308
return referenceOwnershipBuilder;
309309
}
@@ -337,14 +337,14 @@ public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwne
337337
public static OwnedNavigationBuilder ToTable(
338338
this OwnedNavigationBuilder referenceOwnershipBuilder,
339339
string? name,
340-
Action<TableBuilder> buildAction)
340+
Action<OwnedNavigationTableBuilder> buildAction)
341341
{
342342
Check.NullButNotEmpty(name, nameof(name));
343343
Check.NotNull(buildAction, nameof(buildAction));
344344

345345
referenceOwnershipBuilder.OwnedEntityType.SetTableName(name);
346346
referenceOwnershipBuilder.OwnedEntityType.SetSchema(null);
347-
buildAction(new TableBuilder(name, null, referenceOwnershipBuilder.OwnedEntityType));
347+
buildAction(new OwnedNavigationTableBuilder(name, null, referenceOwnershipBuilder));
348348

349349
return referenceOwnershipBuilder;
350350
}
@@ -362,7 +362,7 @@ public static OwnedNavigationBuilder ToTable(
362362
public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwnerEntity, TRelatedEntity>(
363363
this OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> referenceOwnershipBuilder,
364364
string? name,
365-
Action<TableBuilder<TRelatedEntity>> buildAction)
365+
Action<OwnedNavigationTableBuilder<TRelatedEntity>> buildAction)
366366
where TOwnerEntity : class
367367
where TRelatedEntity : class
368368
{
@@ -371,7 +371,7 @@ public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwne
371371

372372
referenceOwnershipBuilder.OwnedEntityType.SetTableName(name);
373373
referenceOwnershipBuilder.OwnedEntityType.SetSchema(null);
374-
buildAction(new TableBuilder<TRelatedEntity>(name, null, referenceOwnershipBuilder.OwnedEntityType));
374+
buildAction(new OwnedNavigationTableBuilder<TRelatedEntity>(name, null, referenceOwnershipBuilder));
375375

376376
return referenceOwnershipBuilder;
377377
}
@@ -415,15 +415,15 @@ public static OwnedNavigationBuilder ToTable(
415415
this OwnedNavigationBuilder referenceOwnershipBuilder,
416416
string name,
417417
string? schema,
418-
Action<TableBuilder> buildAction)
418+
Action<OwnedNavigationTableBuilder> buildAction)
419419
{
420420
Check.NotNull(name, nameof(name));
421421
Check.NullButNotEmpty(schema, nameof(schema));
422422
Check.NotNull(buildAction, nameof(buildAction));
423423

424424
referenceOwnershipBuilder.OwnedEntityType.SetTableName(name);
425425
referenceOwnershipBuilder.OwnedEntityType.SetSchema(schema);
426-
buildAction(new TableBuilder(name, schema, referenceOwnershipBuilder.OwnedEntityType));
426+
buildAction(new OwnedNavigationTableBuilder(name, schema, referenceOwnershipBuilder));
427427

428428
return referenceOwnershipBuilder;
429429
}
@@ -462,7 +462,7 @@ public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwne
462462
this OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> referenceOwnershipBuilder,
463463
string name,
464464
string? schema,
465-
Action<TableBuilder<TRelatedEntity>> buildAction)
465+
Action<OwnedNavigationTableBuilder<TRelatedEntity>> buildAction)
466466
where TOwnerEntity : class
467467
where TRelatedEntity : class
468468
{
@@ -472,7 +472,7 @@ public static OwnedNavigationBuilder<TOwnerEntity, TRelatedEntity> ToTable<TOwne
472472

473473
referenceOwnershipBuilder.OwnedEntityType.SetTableName(name);
474474
referenceOwnershipBuilder.OwnedEntityType.SetSchema(schema);
475-
buildAction(new TableBuilder<TRelatedEntity>(name, schema, referenceOwnershipBuilder.OwnedEntityType));
475+
buildAction(new OwnedNavigationTableBuilder<TRelatedEntity>(name, schema, referenceOwnershipBuilder));
476476

477477
return referenceOwnershipBuilder;
478478
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.ComponentModel;
5+
6+
namespace Microsoft.EntityFrameworkCore.Metadata.Builders;
7+
8+
/// <summary>
9+
/// Instances of this class are returned from methods when using the <see cref="ModelBuilder" /> API
10+
/// and it is not designed to be directly constructed in your application code.
11+
/// </summary>
12+
public class OwnedNavigationTableBuilder
13+
{
14+
/// <summary>
15+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
16+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
17+
/// any release. You should only use it directly in your code with extreme caution and knowing that
18+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
19+
/// </summary>
20+
[EntityFrameworkInternal]
21+
public OwnedNavigationTableBuilder(string? name, string? schema, OwnedNavigationBuilder referenceOwnershipBuilder)
22+
{
23+
ReferenceOwnershipBuilder = referenceOwnershipBuilder;
24+
Metadata = referenceOwnershipBuilder.OwnedEntityType;
25+
}
26+
27+
/// <summary>
28+
/// The entity type being configured.
29+
/// </summary>
30+
public virtual IMutableEntityType Metadata { get; }
31+
32+
/// <summary>
33+
/// The entity type builder.
34+
/// </summary>
35+
public virtual OwnedNavigationBuilder ReferenceOwnershipBuilder { get; }
36+
37+
/// <summary>
38+
/// Configures the table to be ignored by migrations.
39+
/// </summary>
40+
/// <remarks>
41+
/// See <see href="https://aka.ms/efcore-docs-migrations">Database migrations</see> for more information.
42+
/// </remarks>
43+
/// <param name="excluded">A value indicating whether the table should be managed by migrations.</param>
44+
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
45+
public virtual OwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true)
46+
{
47+
Metadata.SetIsTableExcludedFromMigrations(excluded);
48+
49+
return this;
50+
}
51+
52+
#region Hidden System.Object members
53+
54+
/// <summary>
55+
/// Returns a string that represents the current object.
56+
/// </summary>
57+
/// <returns>A string that represents the current object.</returns>
58+
[EditorBrowsable(EditorBrowsableState.Never)]
59+
public override string? ToString()
60+
=> base.ToString();
61+
62+
/// <summary>
63+
/// Determines whether the specified object is equal to the current object.
64+
/// </summary>
65+
/// <param name="obj">The object to compare with the current object.</param>
66+
/// <returns><see langword="true" /> if the specified object is equal to the current object; otherwise, <see langword="false" />.</returns>
67+
[EditorBrowsable(EditorBrowsableState.Never)]
68+
public override bool Equals(object? obj)
69+
=> base.Equals(obj);
70+
71+
/// <summary>
72+
/// Serves as the default hash function.
73+
/// </summary>
74+
/// <returns>A hash code for the current object.</returns>
75+
[EditorBrowsable(EditorBrowsableState.Never)]
76+
public override int GetHashCode()
77+
=> base.GetHashCode();
78+
79+
#endregion
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.EntityFrameworkCore.Metadata.Builders;
5+
6+
/// <summary>
7+
/// Instances of this class are returned from methods when using the <see cref="ModelBuilder" /> API
8+
/// and it is not designed to be directly constructed in your application code.
9+
/// </summary>
10+
/// <typeparam name="TEntity">The entity type being configured.</typeparam>
11+
public class OwnedNavigationTableBuilder<TEntity> : OwnedNavigationTableBuilder
12+
where TEntity : class
13+
{
14+
/// <summary>
15+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
16+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
17+
/// any release. You should only use it directly in your code with extreme caution and knowing that
18+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
19+
/// </summary>
20+
[EntityFrameworkInternal]
21+
public OwnedNavigationTableBuilder(string? name, string? schema, OwnedNavigationBuilder referenceOwnershipBuilder)
22+
: base(name, schema, referenceOwnershipBuilder)
23+
{
24+
}
25+
26+
/// <summary>
27+
/// Configures the table to be ignored by migrations.
28+
/// </summary>
29+
/// <remarks>
30+
/// See <see href="https://aka.ms/efcore-docs-migrations">Database migrations</see> for more information.
31+
/// </remarks>
32+
/// <param name="excluded">A value indicating whether the table should be managed by migrations.</param>
33+
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
34+
public new virtual OwnedNavigationTableBuilder<TEntity> ExcludeFromMigrations(bool excluded = true)
35+
=> (OwnedNavigationTableBuilder<TEntity>)base.ExcludeFromMigrations(excluded);
36+
}

src/EFCore.Relational/Metadata/Builders/TableBuilder.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,22 @@ public class TableBuilder
1818
/// doing so can result in application failures when updating to a new Entity Framework Core release.
1919
/// </summary>
2020
[EntityFrameworkInternal]
21-
public TableBuilder(string? name, string? schema, IMutableEntityType entityType)
21+
public TableBuilder(string? name, string? schema, EntityTypeBuilder entityTypeBuilder)
2222
{
23-
Metadata = entityType;
23+
EntityTypeBuilder = entityTypeBuilder;
24+
Metadata = entityTypeBuilder.Metadata;
2425
}
2526

2627
/// <summary>
2728
/// The entity type being configured.
2829
/// </summary>
2930
public virtual IMutableEntityType Metadata { get; }
3031

32+
/// <summary>
33+
/// The entity type builder.
34+
/// </summary>
35+
public virtual EntityTypeBuilder EntityTypeBuilder { get; }
36+
3137
/// <summary>
3238
/// Configures the table to be ignored by migrations.
3339
/// </summary>

src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public class TableBuilder<TEntity> : TableBuilder
1818
/// doing so can result in application failures when updating to a new Entity Framework Core release.
1919
/// </summary>
2020
[EntityFrameworkInternal]
21-
public TableBuilder(string? name, string? schema, IMutableEntityType entityType)
22-
: base(name, schema, entityType)
21+
public TableBuilder(string? name, string? schema, EntityTypeBuilder entityTypeBuilder)
22+
: base(name, schema, entityTypeBuilder)
2323
{
2424
}
2525

0 commit comments

Comments
 (0)