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
- Make the keyColumnTypes array length equal to the keyColumns array length, one store type string per key column.
- If you do not need explicit types, remove keyColumnTypes entirely and rely on the model to resolve mappings.
- 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
- Always build keyColumnTypes and keyColumns from the same source list so lengths stay in sync.
- Prefer omitting keyColumnTypes and letting the model resolve types.
- Add a unit test that asserts every DeleteData operation in a migration has matching array lengths.
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
- values were provided in CreateIndexOperations.IsDescending…
- The data deletion operation on
- The number of column types
- The number of key column types
- The number of key values
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)