dotnet/efcore · error · InvalidOperationException

A rows affected parameter, result column or return value…

Error message

A rows affected parameter, result column or return value cannot be configured on stored procedure '{sproc}' because it is used for insertion. Rows affected values are only allowed on stored procedures performing updating or deletion.

What it means

Thrown when an INSERT stored procedure mapping is configured with a rows-affected return value: IsRowsAffectedReturned, a rows-affected parameter (FindRowsAffectedParameter), or a rows-affected result column (FindRowsAffectedResultColumn). Insert sprocs always insert exactly one row from EF's perspective, so a rows-affected value is meaningless and prohibited.

Solutions

  1. Remove the .RowsAffectedReturn() / .RowsAffectedParameter(...) / .RowsAffectedResultColumn(...) call from the InsertUsingStoredProcedure configuration.
  2. Keep rows-affected configuration only on UpdateUsingStoredProcedure and DeleteUsingStoredProcedure.

Example fix

// before
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp =>
    {
        sp.HasParameter(o => o.CustomerId);
        sp.RowsAffectedReturn(); // illegal for insert
    });

// after
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp => sp.HasParameter(o => o.CustomerId));
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in model.GetEntityTypes())
{
    var insert = et.GetInsertStoredProcedure();
    if (insert == null) continue;
    if (insert.IsRowsAffectedReturned
        || insert.FindRowsAffectedParameter() != null
        || insert.FindRowsAffectedResultColumn() != null)
    {
        Console.WriteLine($"Insert sproc {insert.Name} must not configure rows-affected.");
    }
}

Prevention

When it happens

Trigger: Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:915 when the library encounters an invalid state.

Common situations: Copy-pasting an update sproc configuration to an insert sproc without removing the rows-affected call; switching a sproc from update to insert semantics; misreading docs and assuming rows-affected is universal.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:915

            }

            if (properties.Count > 0)
            {
                throw new InvalidOperationException(
                    RelationalStrings.StoredProcedurePropertiesNotMapped(
                        entityType.DisplayName(),
                        storeObjectIdentifier.DisplayName(),
                        properties.Values.Format()));
            }
        }

        if (sproc.IsRowsAffectedReturned
            || sproc.FindRowsAffectedParameter() != null
            || sproc.FindRowsAffectedResultColumn() != null)
        {
            if (storeObjectIdentifier.StoreObjectType == StoreObjectType.InsertStoredProcedure)
            {
                throw new InvalidOperationException(
                    RelationalStrings.StoredProcedureRowsAffectedForInsert(
                        storeObjectIdentifier.DisplayName()));
            }

            if (originalValueProperties.Values.FirstOrDefault(p => p.IsConcurrencyToken) is { } missedConcurrencyToken)
            {
                logger.StoredProcedureConcurrencyTokenNotMapped(entityType, missedConcurrencyToken, storeObjectIdentifier.DisplayName());
            }

            if (sproc.ResultColumns.Any(c => c != sproc.FindRowsAffectedResultColumn()))
            {
                throw new InvalidOperationException(
                    RelationalStrings.StoredProcedureRowsAffectedWithResultColumns(
                        entityType.DisplayName(),
                        storeObjectIdentifier.DisplayName()));
            }
        }
    }

View on GitHub (pinned to 3a2006ef56)