dotnet/efcore · error · InvalidOperationException
The operation '{operation}' cannot be performed on keyless e
Error message
The operation '{operation}' cannot be performed on keyless entity type '{entityType}', since it contains an operator not natively supported by the database provider. What it means
Thrown when ExecuteUpdate (or ExecuteDelete) targets a keyless entity type. Bulk update/delete generates an INNER JOIN on the entity's primary key columns; a keyless entity has no PK, so the join cannot be constructed and the operation is rejected with the 'operator not natively supported' framing.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs:98
if (!IsMemberAccess(
RemapLambdaBody(source, firstPropertySelector).UnwrapTypeConversion(out _),
RelationalDependencies.Model,
out var baseExpression)
|| _sqlTranslator.TranslateProjection(baseExpression) is not StructuralTypeShaperExpression shaper)
{
throw new InvalidOperationException(RelationalStrings.InvalidPropertyInSetProperty(firstPropertySelector));
}
// TODO: #36336
if (shaper.StructuralType is not IEntityType entityType)
{
throw new InvalidOperationException(
RelationalStrings.ExecuteUpdateSubqueryNotSupportedOverComplexTypes(shaper.StructuralType.DisplayName()));
}
if (entityType.FindPrimaryKey() is not { } pk)
{
throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnKeylessEntityTypeWithUnsupportedOperator(
nameof(EntityFrameworkQueryableExtensions.ExecuteUpdate),
entityType.DisplayName()));
}
// Generate the INNER JOIN around the original query, on the PK properties.
var outer = (ShapedQueryExpression)Visit(new EntityQueryRootExpression(entityType));
var inner = source;
var outerParameter = Expression.Parameter(entityType.ClrType);
var outerKeySelector = Expression.Lambda(outerParameter.CreateKeyValuesExpression(pk.Properties), outerParameter);
var firstPropertyLambdaExpression = setters[0].PropertySelector;
var entitySource = GetEntitySource(RelationalDependencies.Model, firstPropertyLambdaExpression.Body);
var innerKeySelector = Expression.Lambda(
entitySource.CreateKeyValuesExpression(pk.Properties), firstPropertyLambdaExpression.Parameters);
var joinPredicate = CreateJoinPredicate(outer, outerKeySelector, inner, innerKeySelector);
Check.DebugAssert(joinPredicate != null, "Join predicate shouldn't be null");View on GitHub (pinned to 3a2006ef56)
Solutions
- Add a primary key to the entity type via HasKey(...) / Key(...) so ExecuteUpdate can join back to the table.
- If the type is genuinely keyless and read-only, do not call ExecuteUpdate/ExecuteDelete on it; load, mutate, and SaveChanges on a keyed entity instead.
- Switch the bulk operation to run against a keyed entity type that maps to the same table.
Example fix
// before modelBuilder.Entity<EagleQuery>().HasNoKey(); await ctx.Set<EagleQuery>().ExecuteUpdateAsync(s => s.SetProperty(e => e.Name, "x")); // after modelBuilder.Entity<Eagle>().HasKey(e => e.Id); await ctx.Set<Eagle>().ExecuteUpdateAsync(s => s.SetProperty(e => e.Name, "x"));
Defensive patterns
Strategy: validation
Validate before calling
// Verify the entity has a primary key before calling ExecuteUpdate/ExecuteDelete.
IEntityType? et = ctx.Model.FindEntityType(typeof(EagleQuery));
if (et?.FindPrimaryKey() is null)
{
throw new InvalidOperationException($"{et?.DisplayName()} is keyless; bulk update not supported.");
}
await ctx.Set<EagleQuery>().ExecuteUpdateAsync(s => s.SetProperty(e => e.Name, "x")); Try / catch
try { await query.ExecuteUpdateAsync(setters); }
catch (InvalidOperationException ex) when (ex.Message.Contains("keyless entity type"))
{
logger.LogWarning("Bulk update on keyless entity is not supported: {Msg}", ex.Message);
// fall back to load + SaveChanges on a keyed entity
} Prevention
- Reserve HasNoKey for genuinely read-only view/TVF mappings.
- Add a build-time test that asserts every entity used with ExecuteUpdate has a key.
- Document keyless types in the project as read-only.
When it happens
Trigger: Defining an entity type with HasNoKey() and then calling ExecuteUpdate/ExecuteDelete on a query rooted at it, or on a query (e.g. a view or TVF) that resolves to a keyless entity. The source region shows the check `entityType.FindPrimaryKey() is not { } pk` failing for ExecuteUpdate; the same helper fires for ExecuteDelete in the sibling file.
Common situations: Mapping database views, raw SQL results, or query results as keyless entities and attempting bulk modifications; forgetting that a HasNoKey entity cannot participate in write operations.
Related errors
- 'ExecuteUpdate' or 'ExecuteDelete' was called on entity type
- The operation 'ExecuteDelete' requires an entity type which
- The operation '{operation}' cannot be performed on keyless e
- The following lambda argument to 'SetProperty' does not repr
- 'ExecuteUpdate' is being used over a LINQ operator which isn
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e9dc841420cc5a4b.
Report an issue: GitHub.