dotnet/efcore · error · InvalidOperationException

The data insertion operation on

Error message

The data insertion 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

To generate SQL for an InsertDataOperation EF needs the column types. It can get them from the attached model (via property mappings) or from the operation's explicit ColumnTypes. If neither is present — ColumnTypes is null AND the model passed to Generate is null — there is no way to infer how to render the values, so it throws.

Solutions

  1. Supply columnTypes for every InsertData operation when no model is available.
  2. Pass the target IModel into the migrator/Generate call so EF can map columns to properties.
  3. Regenerate the migration so the model snapshot is wired up automatically.

Example fix

// before — no model, no types
var op = new InsertDataOperation
{
    Table = "Products",
    Columns = new[] { "Id", "Name" },
    Values = new object[,] { { 1, "A" } }
};
// generator.Generate(new[] { op }, model: null, ...) -> throws

// after — supply column types
var op = new InsertDataOperation
{
    Table = "Products",
    Columns = new[] { "Id", "Name" },
    ColumnTypes = new[] { "int", "nvarchar(100)" },
    Values = new object[,] { { 1, "A" } }
};
Defensive patterns

Strategy: validation

Validate before calling

// Ensure InsertData can resolve types: model present OR columnTypes set
static void ValidateInsertModelOrTypes(InsertDataOperation op, IModel? model)
{
    if (op.ColumnTypes == null && model == null)
        throw new ArgumentException(
            $"InsertData on {op.Table} has no model and no columnTypes; " +
            "cannot infer SQL types.");
}

Type guard

static bool InsertTypesResolvable(InsertDataOperation op, IModel? model)
    => op.ColumnTypes != null || model != null;

Prevention

When it happens

Trigger: An InsertDataOperation is built without a model context (e.g. operations applied directly via migrationBuilder without a snapshot) and ColumnTypes was not set. Common when invoking Generate on a standalone list of operations or running a hand-authored migration that omits both the model and column types.

Common situations: Building migration commands at runtime from raw operations; applying operations through a custom pipeline that does not pass the model; removing column types while also detaching the model in tests.

Related errors


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

Appendix: source

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

            throw new InvalidOperationException(
                RelationalStrings.InsertDataOperationValuesCountMismatch(
                    operation.Values.GetLength(1), operation.Columns.Length,
                    FormatTable(operation.Table, operation.Schema ?? model?.GetDefaultSchema())));
        }

        if (operation.ColumnTypes != null
            && operation.Columns.Length != operation.ColumnTypes.Length)
        {
            throw new InvalidOperationException(
                RelationalStrings.InsertDataOperationTypesCountMismatch(
                    operation.ColumnTypes.Length, operation.Columns.Length,
                    FormatTable(operation.Table, operation.Schema ?? model?.GetDefaultSchema())));
        }

        if (operation.ColumnTypes == null
            && model == null)
        {
            throw new InvalidOperationException(
                RelationalStrings.InsertDataOperationNoModel(
                    FormatTable(operation.Table, operation.Schema ?? model?.GetDefaultSchema())));
        }

        var propertyMappings = operation.ColumnTypes == null
            ? GetPropertyMappings(operation.Columns, operation.Table, operation.Schema, model)
            : null;

        for (var i = 0; i < operation.Values.GetLength(0); i++)
        {
            var modificationCommand = Dependencies.ModificationCommandFactory.CreateNonTrackedModificationCommand(
                new NonTrackedModificationCommandParameters(
                    operation.Table, operation.Schema ?? model?.GetDefaultSchema(), SensitiveLoggingEnabled));
            modificationCommand.EntityState = EntityState.Added;

            for (var j = 0; j < operation.Columns.Length; j++)
            {
                var name = operation.Columns[j];

View on GitHub (pinned to 3a2006ef56)