Skip to content

Improve pruning to properly support ExecuteUpdate #31407

@roji

Description

@roji

#31406, allowed ExecuteUpdate with entity splitting (as long as all updated columns are on the same table). While this works well, if you try to change columns on a non-main (split) table on SQL Server, this fails (see test NonSharedModelBulkUpdatesTestBase.Update_single_table_in_entity_with_entity_splitting); - this does work on SQLite, due to a different query shape.

The root cause here is that we generate an INNER JOIN between the main table and the split table, where the split table is the one being updated. When we prune the expression after translation (SelectExpressionPruningExpressionVisitor), we don't find any reference to the joined table within the SelectExpression: the only references are from the UpdateExpression's column setters, but the pruning visitor doesn't see them.

The proper fix here would be to make pruning a proper visitor, with specific handling for ExecuteUpdate. More generally, we should consider not having UpdateExpression be a wrapper around SelectExpression, but its own expression type that directly contains its elements. This may involve significant work as all postprocessing visitors would need to handle it properly, but it's the more correct representation and would prevent bugs like this from the get-go.

See also:

  • #31083, which is related (pruning also doesn't visit all SelectExpressions since it isn't a real visitor).
  • #31049, which is about extracting the visitation out of SelectExpression so that providers can extend for provider-specific expressions (such as OPENJSON).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions