dotnet/efcore · error · InvalidOperationException

The number of key column types

Error message

The number of key column types ({typesCount}) doesn't match the number of key columns ({columnsCount}) for the data deletion operation on '{table}'. Provide the same number of key column types and key columns.

What it means

Thrown when generating SQL for a DeleteData migration operation where the user supplied KeyColumnTypes but its length differs from KeyColumns. EF needs every key column to have a matching declared store type so it can resolve a type mapping for the parameterized delete.

Solutions

  1. Make the keyColumnTypes array length equal to the keyColumns array length, one store type string per key column.
  2. If you do not need explicit types, remove keyColumnTypes entirely and rely on the model to resolve mappings.
  3. Regenerate the migration with Add-Migration / dotnet ef migrations add so the scaffolder writes consistent arrays.

Example fix

// before
migrationBuilder.DeleteData(
    table: "Users",
    keyColumns: new[] { "TenantId", "Id" },
    keyValues: new object[,] { { 1, 10 } },
    keyColumnTypes: new[] { "int" }); // length 1 != 2

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

Strategy: validation

Validate before calling

void ValidateDeleteData(string table, string[] keyColumns, string[]? keyColumnTypes, object[,] keyValues)
{
    if (keyColumnTypes is not null && keyColumnTypes.Length != keyColumns.Length)
        throw new ArgumentException($"{table}: keyColumnTypes({keyColumnTypes.Length}) != keyColumns({keyColumns.Length})");
    if (keyValues.GetLength(1) != keyColumns.Length)
        throw new ArgumentException($"{table}: keyValues dim1 != keyColumns");
}

Prevention

When it happens

Trigger: Calling migrationBuilder.DeleteData(...) with a keyColumnTypes: array whose element count differs from keyColumns:. Generated when MigrationsSqlGenerator.GenerateModificationCommands(DeleteDataOperation) runs and operation.KeyColumnTypes != null && operation.KeyColumns.Length != operation.KeyColumnTypes.Length.

Common situations: Hand-edited migration where a column was added/removed from keyColumns but keyColumnTypes was not updated. Migrations written for providers that require explicit types (e.g. SQLite) where a composite key column was missed.

Related errors


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

Appendix: source

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

    /// </summary>
    /// <param name="operation">The data operation to generate commands for.</param>
    /// <param name="model">The model.</param>
    /// <returns>The commands that correspond to the given operation.</returns>
    protected virtual IEnumerable<IReadOnlyModificationCommand> GenerateModificationCommands(
        DeleteDataOperation operation,
        IModel? model)
    {
        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++)
        {

View on GitHub (pinned to 3a2006ef56)