{"record":{"id":"80e1b14931572b71","repo":"dotnet/efcore","slug":"the-rows-affected-result-column-cannot-be-added-to","errorCode":null,"errorMessage":"The rows affected result column cannot be added to the stored procedure '{sproc}' because the rows affected are already returned via another column, via a parameter or via the stored procedure return value.","messagePattern":"The rows affected result column cannot be added to the stored procedure '(.+?)' because the rows affected are already returned via another column, via a parameter or via the stored procedure return value\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Metadata/Internal/StoredProcedure.cs","lineNumber":653,"sourceCode":"    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public virtual StoredProcedureResultColumn? FindRowsAffectedResultColumn()\n        => _rowsAffectedResultColumn;\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public virtual StoredProcedureResultColumn AddRowsAffectedResultColumn()\n    {\n        if (_rowsAffectedResultColumn != null\n            || _rowsAffectedParameter != null\n            || _isRowsAffectedReturned)\n        {\n            throw new InvalidOperationException(\n                RelationalStrings.StoredProcedureDuplicateRowsAffectedResultColumn(\n                    ((IReadOnlyStoredProcedure)this).GetStoreIdentifier()?.DisplayName()));\n        }\n\n        var resultColumn = new StoredProcedureResultColumn(this, forRowsAffected: true, propertyName: null);\n        _resultColumns.Add(resultColumn);\n        _rowsAffectedResultColumn = resultColumn;\n\n        return resultColumn;\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public override string ToString()","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Metadata/Internal/StoredProcedure.cs#L635-L671","documentation":"Thrown by StoredProcedure.AddRowsAffectedResultColumn when any rows-affected capture already exists — a rows-affected result column, a rows-affected parameter, or the IsRowsAffectedReturned flag. EF allows exactly one rows-affected channel per stored procedure.","triggerScenarios":"StoredProcedure.cs:649-656: _rowsAffectedResultColumn != null || _rowsAffectedParameter != null || _isRowsAffectedReturned. Produced by calling AddRowsAffectedResultColumn() after ReturnsRowsAffected() or AddRowsAffectedParameter().","commonSituations":"Mixing .ReturnsRowsAffected() with .RowsAffectedResultColumn(); scaffolding then re-stacking config; copying insert config to update without removing the return-value setting.","solutions":["Pick one rows-affected mechanism and remove the others before adding the result column.","If you want a result column instead of the return value, do not call ReturnsRowsAffected().","Audit sproc builder calls so only one channel is configured."],"exampleFix":"// before\nvar s = eb.InsertStoredProcedure();\ns.ReturnsRowsAffected();\ns.AddRowsAffectedResultColumn(); // throws\n\n// after\nvar s = eb.InsertStoredProcedure();\ns.AddRowsAffectedResultColumn();","handlingStrategy":"validation","validationCode":"static StoredProcedureResultColumn AddRowsAffectedResultColumnOnce(StoredProcedure sproc)\n{\n    if (sproc.FindRowsAffectedResultColumn() is not null\n        || sproc.FindRowsAffectedParameter() is not null\n        || sproc.IsRowsAffectedReturned)\n    {\n        throw new InvalidOperationException(\"Rows affected already captured on this sproc.\");\n    }\n    return sproc.AddRowsAffectedResultColumn();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use exactly one rows-affected mechanism per sproc.","Keep sproc config in a single builder method."],"tags":["relational","stored-procedure","rows-affected","duplicate"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}