dotnet/efcore · error · InvalidOperationException

The number of key values

Error message

The number of key values ({valuesCount}) doesn't match the number of key columns ({columnsCount}) for the data modification operation on '{table}'. Provide the same number of key values and key columns.

What it means

Thrown when an UpdateData operation's KeyValues 2D array second dimension does not match the number of KeyColumns. Each row of KeyValues must contain exactly one value per key column so EF can build a correct WHERE clause.

Solutions

  1. Resize the keyValues 2D array so its second dimension equals keyColumns.Length.
  2. Add the missing key column to both keyColumns and each row of keyValues.
  3. Re-scaffold the migration with dotnet ef migrations add to regenerate consistent arrays.

Example fix

// before
migrationBuilder.UpdateData(
    table: "Users",
    keyColumns: new[] { "TenantId", "Id" },
    keyValues: new object[,] { { 1 } }, // 1 value, 2 key columns
    columns: new[] { "Name" },
    values: new object[,] { { "x" } });

// after
migrationBuilder.UpdateData(
    table: "Users",
    keyColumns: new[] { "TenantId", "Id" },
    keyValues: new object[,] { { 1, 10 } },
    columns: new[] { "Name" },
    values: new object[,] { { "x" } });
Defensive patterns

Strategy: validation

Validate before calling

static void CheckKeyShape(string[] keyColumns, object[,] keyValues, string table)
{
    if (keyValues.GetLength(1) != keyColumns.Length)
        throw new ArgumentException($"{table}: keyValues second dimension must equal keyColumns.Length");
}

Prevention

When it happens

Trigger: migrationBuilder.UpdateData(...) where keyValues.GetLength(1) (values per row) != keyColumns.Length. Triggered in GenerateModificationCommands(UpdateDataOperation) at the first shape check.

Common situations: Composite key where one column was forgotten in keyValues. Passing a jagged-looking 2D array mis-sized. Editing a generated migration and dropping a key column without resizing values.

Related errors


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

Appendix: source

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

        }

        builder.Append(sqlBuilder.ToString());
        EndStatement(builder);
    }

    /// <summary>
    ///     Generates the commands that correspond to the given operation.
    /// </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(
        UpdateDataOperation operation,
        IModel? model)
    {
        if (operation.KeyColumns.Length != operation.KeyValues.GetLength(1))
        {
            throw new InvalidOperationException(
                RelationalStrings.UpdateDataOperationKeyValuesCountMismatch(
                    operation.KeyValues.GetLength(1), operation.KeyColumns.Length, FormatTable(operation.Table, operation.Schema)));
        }

        if (operation.Columns.Length != operation.Values.GetLength(1))
        {
            throw new InvalidOperationException(
                RelationalStrings.UpdateDataOperationValuesCountMismatch(
                    operation.Values.GetLength(1), operation.Columns.Length, FormatTable(operation.Table, operation.Schema)));
        }

        if (operation.KeyValues.GetLength(0) != operation.Values.GetLength(0))
        {
            throw new InvalidOperationException(
                RelationalStrings.UpdateDataOperationRowCountMismatch(
                    operation.Values.GetLength(0), operation.KeyValues.GetLength(0), FormatTable(operation.Table, operation.Schema)));
        }

View on GitHub (pinned to 3a2006ef56)