dotnet/efcore · error · InvalidOperationException

The data deletion operation on

Error message

The data deletion operation on '{table}' is not associated with a model. Either add a model to the migration, or specify the column types in all data operations.

What it means

Thrown for a DeleteData operation when neither KeyColumnTypes nor a model is available. Without one of them EF cannot determine the store type for each key parameter, so it refuses to emit SQL. The migration must either be tied to a model or declare column types explicitly.

Solutions

  1. Pass keyColumnTypes for every key column so EF can resolve type mappings without a model.
  2. Ensure the migration is produced via Add-Migration so it carries a BuildTargetModel method that supplies the IModel.
  3. If invoking MigrationBuilder manually, supply the model through the Migrator / migrations infrastructure rather than calling Generate directly.

Example fix

// before
migrationBuilder.DeleteData(
    table: "Users",
    keyColumns: new[] { "Id" },
    keyValues: new object[,] { { 10 } });

// after
migrationBuilder.DeleteData(
    table: "Users",
    keyColumns: new[] { "Id" },
    keyColumnTypes: new[] { "int" },
    keyValues: new object[,] { { 10 } });
Defensive patterns

Strategy: validation

Validate before calling

void EnsureDeleteDataResolvable(string[]? keyColumnTypes, IModel? model, string table)
{
    if (keyColumnTypes is null && model is null)
        throw new InvalidOperationException($"{table}: DeleteData needs either keyColumnTypes or a model.");
}

Prevention

When it happens

Trigger: migrationBuilder.DeleteData(...) with no keyColumnTypes, executed in a context where the migration has no target model (model == null). Common with standalone MigrationBuilder instances used outside the Migrator, or with providers that pass null model.

Common situations: Calling migrationBuilder.BuildTargetModel-less pipelines. Design-time scaffolding that runs operations without an IModel. Removing the [DbContext] target from a migration. Using a migrations-only assembly that has no DbContext.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/cb1878f5861b7a6a. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs:985

        if (operation.KeyColumns.Length != operation.KeyValues.GetLength(1))
        {
            throw new InvalidOperationException(
                RelationalStrings.DeleteDataOperationValuesCountMismatch(
                    operation.KeyValues.GetLength(1), operation.KeyColumns.Length, FormatTable(operation.Table, operation.Schema)));
        }

        if (operation.KeyColumnTypes != null
            && operation.KeyColumns.Length != operation.KeyColumnTypes.Length)
        {
            throw new InvalidOperationException(
                RelationalStrings.DeleteDataOperationTypesCountMismatch(
                    operation.KeyColumnTypes.Length, operation.KeyColumns.Length, FormatTable(operation.Table, operation.Schema)));
        }

        if (operation.KeyColumnTypes == null
            && model == null)
        {
            throw new InvalidOperationException(
                RelationalStrings.DeleteDataOperationNoModel(
                    FormatTable(operation.Table, operation.Schema)));
        }

        var keyPropertyMappings = operation.KeyColumnTypes == null
            ? GetPropertyMappings(operation.KeyColumns, operation.Table, operation.Schema, model)
            : null;

        for (var i = 0; i < operation.KeyValues.GetLength(0); i++)
        {
            var modificationCommand = Dependencies.ModificationCommandFactory.CreateNonTrackedModificationCommand(
                new NonTrackedModificationCommandParameters(operation.Table, operation.Schema, SensitiveLoggingEnabled));
            modificationCommand.EntityState = EntityState.Deleted;

            for (var j = 0; j < operation.KeyColumns.Length; j++)
            {
                var name = operation.KeyColumns[j];
                var value = operation.KeyValues[i, j];

View on GitHub (pinned to 3a2006ef56)