dotnet/efcore · error · InvalidOperationException
The rows affected parameter cannot be added to the stored…
Error message
The rows affected parameter cannot be added to the stored procedure '{sproc}' because the rows affected are already returned via another parameter, via the stored procedure return value or via a result column. What it means
EF Core forbids a stored procedure from returning the rows-affected count through more than one channel. AddRowsAffectedParameter() throws when rows affected is already sourced from a parameter, a result column, or the procedure's return value, because the runtime could not disambiguate which channel to read.
Solutions
- Inspect the existing mapping first: call FindRowsAffectedParameter(), FindRowsAffectedResultColumn(), and check IsRowsAffectedReturned before adding a new channel.
- Choose exactly ONE rows-affected source per procedure and remove the duplicate fluent call.
- If the procedure returns rows affected via its RETURN value, use .RowsAffectedReturned() only and do not add a parameter or result column.
- If a parameter must carry rows affected, ensure no .RowsAffectedResultColumn() or .RowsAffectedReturned() was configured for that procedure.
Example fix
// before
modelBuilder.Entity<Order>()
.UpdateUsingStoredProcedure("usp_UpdateOrder", sp =>
{
sp.RowsAffectedReturned();
sp.RowsAffectedParameter(); // throws: already returned
});
// after
modelBuilder.Entity<Order>()
.UpdateUsingStoredProcedure("usp_UpdateOrder", sp =>
{
sp.RowsAffectedReturned();
}); Defensive patterns
Strategy: validation
Validate before calling
// Before adding a rows-affected channel, verify none exists.
var sp = entityType.GetUpdateStoredProcedure();
if (sp is not null
&& sp.FindRowsAffectedParameter() is null
&& sp.FindRowsAffectedResultColumn() is null
&& !sp.IsRowsAffectedReturned)
{
sp.RowsAffectedParameter();
} Type guard
static bool CanAddRowsAffectedParameter(IStoredProcedure sp)
=> sp.FindRowsAffectedParameter() is null
&& sp.FindRowsAffectedResultColumn() is null
&& !sp.IsRowsAffectedReturned; Prevention
- Decide each procedure's single rows-affected channel at design time and document it.
- Centralize stored-procedure builder helpers so the rows-affected choice is made in one place.
- Run model validation ( modelBuilder.FinalizeModel() ) in unit tests to surface config errors early.
When it happens
Trigger: Calling entity.UpdateUsingStoredProcedure(...).RowsAffectedParameter() after a prior .RowsAffectedParameter(), .RowsAffectedResultColumn(), or .RowsAffectedReturned() on the same stored procedure. The guard fires when any of _rowsAffectedParameter, _rowsAffectedResultColumn, or _isRowsAffectedReturned is already set.
Common situations: Migrating a manual stored-procedure mapping where the DBA set rows-affected via the RETURN value, then the developer adds an output parameter; or copy-pasting fluent calls between Insert/Update/Delete procedures; or upgrading EF versions where the default rows-affected strategy changed.
Related errors
- The rows affected result column cannot be added to the…
- ' ' cannot be configured for the parameter ' ' of the…
- The result column for the property
- The entity type ' ' was not found. Ensure that the entity…
- The stored procedure
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/677c0651ebd70e7a.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Metadata/Internal/StoredProcedure.cs:577
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual StoredProcedureParameter? FindRowsAffectedParameter()
=> _rowsAffectedParameter;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual StoredProcedureParameter AddRowsAffectedParameter()
{
if (_rowsAffectedParameter != null
|| _rowsAffectedResultColumn != null
|| _isRowsAffectedReturned)
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureDuplicateRowsAffectedParameter(
((IReadOnlyStoredProcedure)this).GetStoreIdentifier()?.DisplayName()));
}
var parameter = new StoredProcedureParameter(this, rowsAffected: true, propertyName: null, originalValue: null);
_parameters.Add(parameter);
_rowsAffectedParameter = parameter;
return parameter;
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual IReadOnlyList<StoredProcedureResultColumn> ResultColumnsView on GitHub (pinned to 3a2006ef56)