{"record":{"id":"61a8dca1468663aa","repo":"dotnet/efcore","slug":"executeupdatedeleteonentitynotmappedtotable","errorCode":"ExecuteUpdateDeleteOnEntityNotMappedToTable","errorMessage":"'ExecuteUpdate' or 'ExecuteDelete' was called on entity type '{entityType}', but that entity type is not mapped to a table.","messagePattern":"'ExecuteUpdate' or 'ExecuteDelete' was called on entity type '(.+?)', but that entity type is not mapped to a table\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs","lineNumber":45,"sourceCode":"        {\n            case RelationalAnnotationNames.TptMappingStrategy:\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnTPT(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n\n            // Note that we do allow TPC if the target is a leaf type\n            case RelationalAnnotationNames.TpcMappingStrategy when entityType.GetDirectlyDerivedTypes().Any():\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnTPC(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n        }\n\n        // Find the table model that maps to the entity type; there must be exactly one (e.g. no entity splitting).\n        var targetTable = entityType.GetTableMappings().ToList() switch\n        {\n            [] => throw new InvalidOperationException(\n                RelationalStrings.ExecuteUpdateDeleteOnEntityNotMappedToTable(entityType.DisplayName())),\n            [var singleTableMapping] => singleTableMapping.Table,\n            _ => throw new InvalidOperationException(\n                RelationalStrings.ExecuteOperationOnEntitySplitting(\n                    nameof(EntityFrameworkQueryableExtensions.ExecuteDelete), entityType.DisplayName())),\n        };\n        var selectExpression = (SelectExpression)source.QueryExpression;\n\n        // Find the table expression in the SelectExpression that corresponds to the projected entity type.\n        var projectionBindingExpression = (ProjectionBindingExpression)shaper.ValueBufferExpression;\n        var projection = (StructuralTypeProjectionExpression)selectExpression.GetProjection(projectionBindingExpression);\n        var column = projection.BindProperty(shaper.StructuralType.GetProperties().First());\n        var tableExpression = selectExpression.GetTable(column, out var tableIndex);\n\n        // If the projected table expression (the thing to be deleted) isn't a TableExpression (e.g. it's a set operation), we can't\n        // translate to a simple DELETE (which requires a simple target table), and must fall back to rewriting as a subquery.\n        if (tableExpression.UnwrapJoin() is TableExpression unwrappedTableExpression)\n        {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs#L27-L63","documentation":"Thrown when ExecuteDelete/ExecuteUpdate is applied to an entity type that has no table mappings at all (GetTableMappings returns empty). Bulk DML needs a real table to modify; entities mapped only to views (or not mapped to any table) cannot be bulk-updated.","triggerScenarios":"Calling ExecuteDelete/ExecuteUpdate on an entity configured with ToView(nameof(View)) and no ToTable, a keyless query type mapped to a view, or an entity type with no relational mapping.","commonSituations":"Mapping read-only entities to database views and then attempting bulk delete/update; denormalized query-only models; entities that back caches or computed views.","solutions":["Map the entity type to a table with ToTable so bulk DML has a target.","For view-backed read-only entities, perform deletes/updates via raw SQL against the underlying tables using Database.ExecuteSqlRaw.","Use the change tracker only if a table mapping exists; otherwise restructure so a table backs the entity.","Review the model: ensure ToTable is present (or remove ToView-only mapping) for types you intend to mutate."],"exampleFix":"// before\nmodelBuilder.Entity<ReportRow>().ToView(\"v_Report\");\nawait db.ReportRows.ExecuteDeleteAsync();\n// after - map to the underlying table\nmodelBuilder.Entity<ReportRow>().ToTable(\"ReportRows\");\nawait db.ReportRows.ExecuteDeleteAsync();\n// or use raw SQL against the backing table\nawait db.Database.ExecuteSqlRawAsync(\"DELETE FROM ReportRows WHERE ...\");","handlingStrategy":"validation","validationCode":"var hasTable = entityType.GetTableMappings().Any();\nif (!hasTable)\n    throw new InvalidOperationException($\"{entityType.Name} is not mapped to a table; bulk ops need a ToTable mapping.\");","typeGuard":null,"tryCatchPattern":"try { await db.ReportRows.ExecuteDeleteAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not mapped to a table\"))\n{\n    await db.Database.ExecuteSqlRawAsync(\"DELETE FROM ReportRows WHERE ...\");\n}","preventionTips":["Ensure ToTable is set for any entity you bulk-modify.","Treat ToView-only entities as read-only.","Use raw SQL for deletes/updates on view-backed types.","Audit the model for types missing table mappings."],"tags":["executedelete","executeupdate","view-mapping","table-mapping","bulk-operations"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}