{"record":{"id":"b087417c4389fa36","repo":"dotnet/efcore","slug":"executeupdatedeleteonentitynotmappedtotable-b08741","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.ExecuteUpdate.cs","lineNumber":485,"sourceCode":"                            // See #28520 about improving this.\n                            var containerColumnName = complexType.GetContainerColumnName();\n                            if (containerColumnName != null)\n                            {\n                                targetColumnModel = complexType.GetTableMappings()\n                                    .Select(m => m.Table.FindColumn(containerColumnName))\n                                    .SingleOrDefault(c => c is not null);\n                            }\n\n                            break;\n                        }\n\n                        default:\n                            throw new UnreachableException();\n                    }\n\n                    if (targetColumnModel is null)\n                    {\n                        throw new InvalidOperationException(\n                            RelationalStrings.ExecuteUpdateDeleteOnEntityNotMappedToTable(targetProperty.DeclaringType.DisplayName()));\n                    }\n\n                    unwrappedTableExpression = new TableExpression(unwrappedTableExpression.Alias, targetColumnModel.Table);\n                    tableExpression = tableExpression is JoinExpressionBase join\n                        ? join.Update(unwrappedTableExpression)\n                        : unwrappedTableExpression;\n                    var newTables = select.Tables.ToList();\n                    newTables[tableIndex] = tableExpression;\n\n                    // Note that we need to keep the select mutable, because if IsValidSelectExpressionForExecuteDelete below\n                    // returns false, we need to compose on top of it.\n                    select.SetTables(newTables);\n                }\n\n                CheckColumnOnSameTable(column, propertySelector);\n            }\n","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L467-L503","documentation":"In ProcessColumn (line 438-502), when the table expression does not reference an ITable (e.g. it points at a view or a query-defining expression), EF looks up the corresponding mutable table column for the property. If no such column/table mapping exists (targetColumnModel is null at line 483), ExecuteUpdate/ExecuteDelete cannot target any table and throws ExecuteUpdateDeleteOnEntityNotMappedToTable.","triggerScenarios":"Calling ExecuteUpdate or ExecuteDelete on an entity type that is mapped only to a view (ToView, no ToTable), to a function, or to a query (HasNoKey + defining query), so GetTableMappings yields no ITable and no mutable column can be found.","commonSituations":"Read-only view entities mistakenly used for bulk updates; entities configured with ToView instead of ToTable; defining queries (ToQuery) entities; database-first scaffolding that produced view-only mappings.","solutions":["Map the entity to a real table with ToTable so it has a mutable table mapping.","If the entity is genuinely a view, perform the update against the underlying base table entity or via raw SQL.","Remove ToView and let EF map by convention to a table, or add an explicit ToTable."],"exampleFix":"// before (entity mapped only to a view)\nmodelBuilder.Entity<OrderView>().ToView(\"OrderView\").HasNoKey();\ndb.Set<OrderView>().Where(o => o.Stale)\n    .ExecuteDelete();\n\n// after (map to a real table so a mutation target exists)\nmodelBuilder.Entity<OrderView>().ToTable(\"OrderView\");\ndb.Set<OrderView>().Where(o => o.Stale)\n    .ExecuteDelete();","handlingStrategy":"validation","validationCode":"// Verify the entity has a table mapping (not only a view) before mutating.\nforeach (var t in entityType.GetTableMappings()) { /* ok: has a table */ return; }\nthrow new InvalidOperationException(\"Entity is not mapped to a table; ExecuteUpdate/ExecuteDelete will fail.\");","typeGuard":null,"tryCatchPattern":"try { await q.ExecuteDeleteAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not mapped to a table\"))\n{ /* add ToTable mapping, or target the base table entity / raw SQL */ }","preventionTips":["Use ToTable (not just ToView) for entities you intend to mutate.","Reserve HasNoKey/ToView for read-only projections.","After scaffolding, verify view entities are not used in ExecuteUpdate/ExecuteDelete."],"tags":["efcore","executeupdate","executedelete","table-mapping","view"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}