dotnet/efcore · error · InvalidOperationException
'ExecuteUpdate' is being used over type '{structuralType}' w
Error message
'ExecuteUpdate' is being used over type '{structuralType}' which is mapped to JSON; 'ExecuteUpdate' on JSON is not supported. What it means
Thrown when the SetProperty target resolves to a StructuralTypeShaperExpression whose ComplexType is mapped to JSON. EF Core cannot generate an ExecuteUpdate over a complex type that lives inside a JSON column (the JSON column is opaque to the relational update pipeline at this 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 3a2006ef56)
Solutions
- Map the complex type to regular columns (ComplexProperty without ToJson) if you need ExecuteUpdate on its members.
- Update the JSON-mapped complex type via load-modify-SaveChanges instead of ExecuteUpdate.
- Move the updatable scalar out of the JSON complex type into the owning entity.
Example fix
// before
modelBuilder.Entity<Root>().ComplexProperty(r => r.Address, b => b.ToJson("addr"));
await ctx.Set<Root>().ExecuteUpdateAsync(s => s.SetProperty(r => r.Address.City, "x"));
// after
modelBuilder.Entity<Root>().ComplexProperty(r => r.Address);
await ctx.Set<Root>().ExecuteUpdateAsync(s => s.SetProperty(r => r.Address.City, "x")); Defensive patterns
Strategy: validation
Validate before calling
// Detect JSON-mapped complex types before ExecuteUpdate.
foreach (var ct in ctx.Model.GetEntityTypes().SelectMany(e => e.GetComplexProperties()))
if (ct.ComplexType.IsMappedToJson())
logger.LogWarning("Complex type {Name} is JSON-mapped; ExecuteUpdate unsupported.", ct.Name); Prevention
- Do not call ToJson on complex properties that must support ExecuteUpdate.
- Document which complex types are JSON vs column-mapped.
- Use load-modify-SaveChanges for JSON complex types.
When it happens
Trigger: A complex property configured with ToJson (complex-JSON) and ExecuteUpdate targeting one of its scalar members. The source fires inside the StructuralTypeShaperExpression/IComplexType case of the setter switch when complexType.IsMappedToJson() is true.
Common situations: Using the newer complex-JSON mapping and attempting bulk updates; mixing complex types with JSON columns.
Related errors
- ExecuteUpdate over JSON columns is not supported when the co
- 'ExecuteUpdate' is being used over a LINQ operator which isn
- '{operation}' used over owned type '{entityType}' which is m
- 'ExecuteUpdate' cannot currently set a property in a JSON co
- 'ExecuteUpdate' cannot currently set a property in a JSON co
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/cfce8dea8fbd4e83.
Report an issue: GitHub.