dotnet/efcore · error · InvalidOperationException
The operation 'ExecuteDelete' requires an entity type which
Error message
The operation 'ExecuteDelete' requires an entity type which corresponds to the database table to be modified. The current operation is being applied on a non-entity projection. Remove any projection to non-entity types.
What it means
TranslateExecuteDelete runs an IncludePruner over the shaper and then requires the result to be a StructuralTypeShaperExpression whose StructuralType is an IEntityType. If the shaper is anything else (anonymous/DTO projection, complex type, value type), there is no entity table to delete from and ExecuteDelete cannot be translated.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs:17
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
namespace Microsoft.EntityFrameworkCore.Query;
public partial class RelationalQueryableMethodTranslatingExpressionVisitor
{
/// <inheritdoc />
protected override DeleteExpression TranslateExecuteDelete(ShapedQueryExpression source)
{
source = source.UpdateShaperExpression(new IncludePruner().Visit(source.ShaperExpression));
if (source.ShaperExpression is not StructuralTypeShaperExpression { StructuralType: IEntityType entityType } shaper)
{
throw new InvalidOperationException(RelationalStrings.ExecuteDeleteOnNonEntityType);
}
if (entityType.IsMappedToJson())
{
throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnOwnedJsonIsNotSupported("ExecuteDelete", entityType.DisplayName()));
}
switch (entityType.GetMappingStrategy())
{
case RelationalAnnotationNames.TptMappingStrategy:
throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnTPT(
nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),
entityType.DisplayName()));
// Note that we do allow TPC if the target is a leaf type
case RelationalAnnotationNames.TpcMappingStrategy when entityType.GetDirectlyDerivedTypes().Any():View on GitHub (pinned to 3a2006ef56)
Solutions
- Apply ExecuteDelete directly on the DbSet/entity query before any non-entity projection: context.Blogs.Where(...).ExecuteDelete().
- Move the projection after deletion is unnecessary; if you only need to filter, express the filter with Where on the entity, not Select.
- If you must compute the set of keys first, materialize keys to memory then issue a single ExecuteDelete with Contains on the entity: context.Blogs.Where(b => keys.Contains(b.Id)).ExecuteDelete().
Example fix
// before (projection before delete -> 590)
await db.Blogs
.Select(b => new BlogDto { Id = b.Id })
.ExecuteDeleteAsync();
// after (delete on entity, filter with Where)
await db.Blogs
.Where(b => b.Archived)
.ExecuteDeleteAsync(); Defensive patterns
Strategy: validation
Validate before calling
// Ensure ExecuteDelete is applied to an entity query, not a projection.
var elementType = typeof(TSource);
var isEntity = db.Model.FindEntityType(elementType) is not null;
if (!isEntity)
throw new InvalidOperationException($"{elementType} is not a mapped entity; call ExecuteDelete on the entity before projecting."); Prevention
- Call ExecuteDelete on the DbSet/Where chain before any Select.
- When you need a computed set of keys, materialize them and use Contains in the entity-side Where.
- Review refactors that introduce DTOs into delete/update pipelines.
When it happens
Trigger: context.Blogs.Select(b => new BlogDto { ... }).ExecuteDelete(); context.Blogs.Select(b => new { b.Id, b.Title }).ExecuteDelete(); calling ExecuteDelete after a projection that replaces the entity shaper with a non-entity shaper; calling ExecuteDelete over a query rooted on a complex type or keyless view projection.
Common situations: Chaining ExecuteDelete after Select/SelectMany that projects to a DTO or anonymous type; refactoring a query and forgetting that ExecuteDelete must target an entity; mixing read-model projections with bulk-delete intent.
Related errors
- The LINQ expression '{expression}' could not be translated.
- The operation '{operation}' cannot be performed on keyless e
- The operation '{operation}' cannot be performed on keyless e
- 'ExecuteUpdate' or 'ExecuteDelete' was called on entity type
- The LINQ expression '{expression}' could not be translated.
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/9d658c9957aaf581.
Report an issue: GitHub.