dotnet/efcore · error · InvalidOperationException

MultipleTablesInExecuteUpdate

MultipleTablesInExecuteUpdate

Error message

Multiple 'SetProperty' invocations refer to different tables ('{propertySelector1}' and '{propertySelector2}'). A single 'ExecuteUpdate' call can only update the columns of a single table.

What it means

CheckColumnOnSameTable (line 772-784) records the table alias of the first setter's column and verifies every subsequent setter's column lives on the same table. A single UPDATE statement can only target one table, so if two SetProperty calls resolve to columns on different tables, MultipleTablesInExecuteUpdate is thrown, naming both offending selectors.

Source

Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs:781

                }

                var result = _sqlTranslator.TranslateProjection(remappedValueSelector, applyDefaultTypeMapping: false);

                return result is null
                    ? throw new InvalidOperationException(RelationalStrings.InvalidValueInSetProperty(valueSelector.Print()))
                    : result;
            }

            void CheckColumnOnSameTable(ColumnExpression column, LambdaExpression propertySelector)
            {
                if (targetTableAlias is null)
                {
                    targetTableAlias = column.TableAlias;
                    targetTablePropertySelector = propertySelector;
                }
                else if (column.TableAlias != targetTableAlias)
                {
                    throw new InvalidOperationException(
                        RelationalStrings.MultipleTablesInExecuteUpdate(propertySelector.Print(), targetTablePropertySelector!.Print()));
                }
            }

            // If the entire JSON column is being referenced, remove the JsonQueryExpression altogether and just return
            // the column (no need for special JSON modification functions/syntax).
            // See #30768 for stopping producing empty Json{Scalar,Query}Expressions.
            // Otherwise, convert the JsonQueryExpression to a JsonScalarExpression, which is our current representation for a complex
            // JSON in the SQL tree (as opposed to in the shaper) - see #36392.
            static SqlExpression ProcessJsonQuery(JsonQueryExpression jsonQuery)
                => jsonQuery.Path is []
                    ? jsonQuery.JsonColumn
                    : new JsonScalarExpression(
                        jsonQuery.JsonColumn,
                        jsonQuery.Path,
                        jsonQuery.Type,
                        jsonQuery.JsonColumn.TypeMapping,
                        jsonQuery.IsNullable);

View on GitHub (pinned to dbf9771522)

Solutions

  1. Restrict a single ExecuteUpdate to properties of one table; issue separate ExecuteUpdate calls per table.
  2. Map the dependent/owned entity to the same table (table splitting) so all columns share one alias.
  3. Reorder so each ExecuteUpdate call's setters are all on the principal table.

Example fix

// before (User and Profile live on different tables)
db.Users.ExecuteUpdate(s => s
    .SetProperty(u => u.Name, "x")
    .SetProperty(u => u.Profile.Bio, "y"));

// after (one ExecuteUpdate per table)
db.Users.ExecuteUpdate(s => s.SetProperty(u => u.Name, "x"));
db.Profiles.ExecuteUpdate(s => s.SetProperty(p => p.Bio, "y"));
Defensive patterns

Strategy: validation

Validate before calling

// Verify all setter target properties map to the same table before calling ExecuteUpdate.
var tables = setters.Select(s => GetTableFor(s.Property)).Distinct();
if (tables.Count() > 1) throw new InvalidOperationException("Setters target multiple tables; split into separate ExecuteUpdate calls.");

Try / catch

try { await q.ExecuteUpdateAsync(s => s.SetProperty(e => e.A, 1).SetProperty(e => e.Nav.B, 2)); }
catch (InvalidOperationException ex) when (ex.Message.Contains("different tables"))
{ /* issue one ExecuteUpdate per table */ }

Prevention

When it happens

Trigger: Chaining SetProperty calls whose properties map to columns on different tables: e.g. SetProperty(e => e.Name, ...).SetProperty(e => e.Profile.Bio, ...) where Profile is a table-split or owned entity on a separate table, or two entities sharing a table via splitting where EF chose different tables.

Common situations: Table splitting where the dependent lives on a different table; owned entities mapped to their own tables; TPT/TPC inheritance where properties map to different hierarchy tables; attempting a multi-table update in one ExecuteUpdate call.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/2e3fcb2ead9a282f. Report an issue: GitHub.