dotnet/efcore · error · InvalidOperationException
A rows affected parameter, result column or return value can
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
A 'rows affected' value (output parameter, result column, or return value) is used to detect optimistic-concurrency conflicts during Update/Delete. Inserts always succeed for a new row so a rows-affected signal is meaningless and not allowed. The validator at line 909-918 explicitly rejects any rows-affected configuration when the store object is an InsertStoredProcedure.
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 dbf9771522)
Solutions
- Remove the .RowsAffectedParameter() / .RowsAffectedResultColumn() / .ReturnsRowsAffected() call from the Insert sproc mapping.
- Move any rows-affected logic to the Update and/or Delete sproc mappings where it is meaningful.
- If you need to verify an insert succeeded, use the output identity value or wrap the call in a transaction with exception handling.
Example fix
// before
modelBuilder.Entity<Order>()
.InsertStoredProcedure(o => o
.Parameter(p => p.Amount, "amt")
.RowsAffectedParameter("rc"));
// after
modelBuilder.Entity<Order>()
.InsertStoredProcedure(o => o
.Parameter(p => p.Amount, "amt")
.OutputParameter(p => p.Id, "new_id")); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in modelBuilder.Model.GetEntityTypes())
{
var insert = et.GetStoredProcedures()
.FirstOrDefault(s => s.StoreObjectType == StoreObjectType.InsertStoredProcedure);
if (insert != null
&& (insert.IsRowsAffectedReturned
|| insert.FindRowsAffectedParameter() != null
|| insert.FindRowsAffectedResultColumn() != null))
{
throw new InvalidOperationException(
$"Insert sproc for {et.Name} must not configure rows-affected.");
}
} Prevention
- Never call .RowsAffectedParameter()/.RowsAffectedResultColumn()/.ReturnsRowsAffected() on an Insert sproc.
- Reuse sproc builder helpers only for Update/Delete; write a separate Insert helper without rows-affected.
- Add a unit test asserting no Insert sproc has rows-affected configured.
When it happens
Trigger: Calling `.InsertStoredProcedure(...).RowsAffectedParameter("rows")` / `.RowsAffectedResultColumn("rows")` / `.ReturnsRowsAffected()` (or returning rows-affected from the sproc).
Common situations: Reusing the same sproc builder snippet across insert/update/delete operations; assuming all sprocs need the rows-affected pattern that update/delete use for concurrency.
Related errors
- Original value parameter '{parameter}' is not allowed on ins
- Input parameter '{parameter}' of insert stored procedure '{s
- The entity type '{entityType}' was configured to use some st
- The entity type '{entityType}' was configured to use '{sproc
- Both entity type '{entityType1}' and '{entityType2}' were co
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/f7795bb35fae9de1.
Report an issue: GitHub.