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
- Remove the .RowsAffectedReturn() / .RowsAffectedParameter(...) / .RowsAffectedResultColumn(...) call from the InsertUsingStoredProcedure configuration.
- 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
- Keep rows-affected configuration only on update/delete sprocs; never insert.
- Write insert sproc configs from a blank builder, not by cloning an update config.
- Code-review insert sproc mappings for rows-affected calls.
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
- Both ' ' and ' ' are explicitly mapped to the stored…
- Both ' ' and ' ' are mapped to the stored procedure ' '…
- ' ' is mapped to the stored procedure ' ' while ' ' is…
- Input parameter ' ' of update stored procedure ' ' is…
- The entity type ' ' is mapped to the stored procedure ' '…
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)