Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for owned types mapped to same table as well as different tables #26706

Closed
wants to merge 2 commits into from

Conversation

maumar
Copy link
Contributor

@maumar maumar commented Nov 16, 2021

Fix to #26451 - Temporal Table: Owned Entities support
Fix to #26469 - Query: enable temporal tables for table splitting scenarios
Fix to #26705 - Query: model building for temporal table with explicitly defined period columns could fail if conventions are executed in a delayed fashion

Just like any other nav expansion, this only works for AsOf operation.

Added extensibility point to SharedTypeEntityExpandingExpressionVisitor so that we can create temporal table expressions representing owned entities, if their owner is also a temporal table expression.
We also need to match TableExpression information with ITable metadata, for provider specific table-like expressions.

Relaxed validation for table splitting when the table is temporal - it's now allowed as long as all (base type) entities mapped to this table have congruent period and history table mappings.

Column period property is now created explicitly in the temporal table builder rather than relying on conventions to avoid scenario when conventions are delayed and the period property they are supposed to create is not ready by the time we need it.

Fixes #26451
Fixes #26469
Fixes #26705

var foreignKey = navigation.ForeignKey;
if (navigation.IsCollection)
{
var innerShapedQuery = CreateShapedQueryExpression(
targetEntityType, _sqlExpressionFactory.Select(targetEntityType));
var innerSelectExpression = BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@smitpatel some refactoring here compared to 6.0 version, which didn't contain the logic for collection (which is also mapped to different table, the logic is pretty much the same) so I DRY'd it a bit

}

// TODO: should we be match case here or not?
if (!relationalSharedTypeEntityExpansionHelper.TableMatchesMetadata(unwrappedTable, table))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the code that this is supposed to improve matches case in some cases and not the others - what's the right thing here? Is metadata case sensitive in general? @AndriySvyryd @smitpatel

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we should always match case for strings that we control

{
if (!mappedType.IsTemporal())
{
throw new InvalidOperationException("either none or all types mapped to same table must be temporal");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: add resources

var requiredPeriodStartColumnName = default(string);
var requiredPeriodEndColumnName = default(string);

foreach (var mappedType in mappedTypes.Where(t => t.BaseType == null))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we only look at based types - we already check elsewhere that derived types don't specify temporal information on them


return new TemporalPeriodPropertyBuilder(_entityType, propertyName);
}

private void EnsurePeriodPropertyExists(string propertyName)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: this is probably wrong @AndriySvyryd

Copy link
Member

@AndriySvyryd AndriySvyryd Nov 16, 2021

Choose a reason for hiding this comment

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

We should capture EntityTypeBuilder in TableBuilder and flow it here to use .Property() instead

{
ab.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this sucks - every owned entity must have the same (redundant) temporal table mapping - we should be smart enough to propagate this information from the owner, but currently its way too much work (as we would need to do it when the new owned type is added as well as when the owner changes) - #15898 is supposed to make it easier

/// <summary>
/// Returns true if the given table expression matches table metadata, false otherwise.
/// </summary>
public bool TableMatchesMetadata(
Copy link
Member

Choose a reason for hiding this comment

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

The moment we needed to add this, we faulted our own design.

Copy link
Contributor Author

@maumar maumar Nov 16, 2021

Choose a reason for hiding this comment

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

yes, ideally there would be an abstract class for table-like sources (like "tableExpressionBase" and what currently is teb should be named something else?) from which TableExpression and temporalTable expression would inherit. Alternatively TemporalTableExpression should inherit from TableExpression rather than TableExpressionBase, but thats a smell also, since TemporalTableExpression is abstract and TableExpression is not :(

…ent tables

Fix to #26451 - Temporal Table: Owned Entities support
Fix to #26469 - Query: enable temporal tables for table splitting scenarios
Fix to #26705 - Query: model building for temporal table with explicitly defined period columns could fail if conventions are executed in a delayed fashion

Just like any other nav expansion, this only works for AsOf operation.

Added extensibility point to SharedTypeEntityExpandingExpressionVisitor so that we can create temporal table expressions representing owned entities, if their owner is also a temporal table expression.
We also need to match TableExpression information with ITable metadata, for provider specific table-like expressions.

Relaxed validation for table splitting when the table is temporal - it's now allowed as long as all (base type) entities mapped to this table have congruent period and history table mappings.

Column period property is now created explicitly in the temporal table builder rather than relying on conventions to avoid scenario when conventions are delayed and the period property they are supposed to create is not ready by the time we need it.
@@ -1171,7 +1186,12 @@ protected override Expression VisitExtension(Expression extensionExpression)
&& navigation.DeclaringEntityType.IsStrictlyDerivedFrom(entityShaperExpression.EntityType));

var entityProjection = _selectExpression.GenerateWeakEntityProjectionExpression(
targetEntityType, table, identifyingColumn.Name, identifyingColumn.Table, principalNullable);
targetEntityType,
Copy link
Member

Choose a reason for hiding this comment

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

There are no weak entity types anymore

@@ -325,6 +325,9 @@
<data name="TemporalSetOperationOnMismatchedSources" xml:space="preserve">
<value>Set operation can't be applied on entity '{entityType}' because temporal operations on both arguments don't match.</value>
</data>
<data name="TemporalOwnedTypeMappedToDifferentTableOnlySupportedForAsOf" xml:space="preserve">
<value>Only '{operationName}' temporal operation is supported for entitiy that owns another entity which is mapped different table.</value>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<value>Only '{operationName}' temporal operation is supported for entitiy that owns another entity which is mapped different table.</value>
<value>Only '{operationName}' temporal operation is supported for entity types that own an entity mapped to a different table.</value>

}
//[EntityFrameworkInternal]
Copy link
Member

Choose a reason for hiding this comment

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

.

@maumar
Copy link
Contributor Author

maumar commented Jan 13, 2022

this has been done in 1ca6380 instead

@maumar maumar closed this Jan 13, 2022
@smitpatel smitpatel deleted the fix26469_take3 branch May 18, 2022 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants