dotnet/efcore · error · InvalidOperationException
ExecuteUpdateOverJsonIsNotSupported
ExecuteUpdateOverJsonIsNotSupported
Error message
'ExecuteUpdate' is being used over type '{structuralType}' which is mapped to JSON; 'ExecuteUpdate' on JSON is not supported. What it means
In the StructuralTypeShaperExpression case for complex types (line 349-369), if the target complex type itself IsMappedToJson, ExecuteUpdate cannot produce a meaningful update for it and throws ExecuteUpdateOverJsonIsNotSupported. JSON-mapped complex types are not writable through ExecuteUpdate at the whole-type level.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs:361
translatedSetters.Add(new ColumnValueSetter(column, translatedValue));
break;
}
// A table-split complex type is being assigned a new value.
// Generate setters for each of the columns mapped to the comlex type.
case StructuralTypeShaperExpression
{
StructuralType: IComplexType complexType,
ValueBufferExpression: StructuralTypeProjectionExpression
} shaper:
{
Check.DebugAssert(
targetProperty is IComplexProperty complexProperty && complexProperty.ComplexType == complexType,
"PropertyBase should be a complex property referring to the correct complex type");
if (complexType.IsMappedToJson())
{
throw new InvalidOperationException(
RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexType.DisplayName()));
}
var translatedValue = TranslateSetterValueSelector(source, valueSelector, shaper.Type);
ProcessComplexType(shaper, translatedValue);
break;
}
case JsonScalarExpression { Json: ColumnExpression jsonColumn } jsonScalar:
{
var typeMapping = jsonScalar.TypeMapping;
Check.DebugAssert(typeMapping is not null);
// We should never see a JsonScalarExpression without a path - that means we're mapping a JSON scalar directly to a relational column.
// This is in theory possible (e.g. map a DateTime to a 'json' column with a single string timestamp representation inside, instead of to
// SQL Server datetime2), but contrived and unsupported.
Check.DebugAssert(jsonScalar.Path.Count > 0);View on GitHub (pinned to dbf9771522)
Solutions
- If the complex type must be updatable via ExecuteUpdate, map it as a table-split complex type (flattened columns) instead of JSON.
- Update individual scalar columns instead of the whole complex value.
- Fall back to load + mutate + SaveChanges for JSON complex types.
Example fix
// before (Address is ComplexProperty(...).ToJson())
db.Contacts.ExecuteUpdate(s => s.SetProperty(
c => c.Address, new Address { City = "NYC" }));
// after (map Address as flattened complex columns, not JSON)
modelBuilder.Entity<Contact>().ComplexProperty(c => c.Address);
db.Contacts.ExecuteUpdate(s => s.SetProperty(
c => c.Address.City, "NYC")); Defensive patterns
Strategy: validation
Validate before calling
// Check whether the target complex type is JSON-mapped before assigning it whole.
var cp = entityType.GetComplexProperties().FirstOrDefault(p => p.Name == "Address");
bool jsonComplex = cp?.ComplexType.IsMappedToJson() == true;
if (jsonComplex) throw new InvalidOperationException("Use flattened complex type or update scalars."); Try / catch
try { await q.ExecuteUpdateAsync(s => s.SetProperty(e => e.Address, value)); }
catch (InvalidOperationException ex) when (ex.Message.Contains("mapped to JSON"))
{ /* remap as flattened complex type or update scalar sub-properties */ } Prevention
- Map updatable complex types as flattened columns, not JSON.
- Update scalar sub-properties rather than whole JSON complex values.
- Standardize on one mapping mode per aggregate root.
When it happens
Trigger: SetProperty assigning an entire JSON-mapped complex type value, e.g. SetProperty(e => e.JsonComplexProperty, new MyComplexType { ... }) where the complex property is configured to live inside a JSON column.
Common situations: Using ComplexProperty(...).ToJson() (JSON-mapped complex type) and attempting a whole-value ExecuteUpdate on it; mixing table-split complex types with JSON complex types and reusing the same update code for both.
Related errors
- ExecuteOperationOnOwnedJsonIsNotSupported
- JsonExecuteUpdateNotSupportedWithOwnedEntities
- ExecuteUpdateCannotSetJsonPropertyToNonJsonColumn
- ExecuteUpdateCannotSetJsonPropertyToArbitraryExpression
- IncompatibleComplexTypesInAssignment
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/f90f3477f97844ba.
Report an issue: GitHub.