dotnet/efcore · error · InvalidOperationException

The property ' . ' is mapped to a result column of the…

Error message

The property '{entityType}.{property}' is mapped to a result column of the stored procedure '{sproc}', but it is also mapped to an output parameter. A store-generated property can only be mapped to one of these.

What it means

Thrown when a property is mapped to BOTH a result column and an output parameter of the same insert/update sproc (validator walks sproc.ResultColumns and tries to remove each result-column property from storeGeneratedProperties; if it was already consumed by an output parameter earlier, the set removal fails). A store-generated property may be read back through only one channel — result column OR output parameter, not both.

Solutions

  1. Choose one read-back mechanism: drop .HasOutputParameter(p => p.Foo) and keep .HasResultColumn(p => p.Foo), or vice versa.
  2. If the sproc genuinely returns both, split the property into two mapped properties — but that is rarely correct; instead align the sproc to return the value once.

Example fix

// before
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp =>
    {
        sp.HasOutputParameter(o => o.OrderId);
        sp.HasResultColumn(o => o.OrderId); // duplicate read-back
    });

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

Strategy: validation

Validate before calling

foreach (var et in model.GetEntityTypes())
{
    foreach (var sproc in new[] { et.GetInsertStoredProcedure(), et.GetUpdateStoredProcedure() })
    {
        if (sproc == null) continue;
        var outputProps = sproc.Parameters
            .Where(p => p.Direction != System.Data.ParameterDirection.Input && p.PropertyName != null)
            .Select(p => p.PropertyName)
            .ToHashSet();
        foreach (var rc in sproc.ResultColumns.Where(c => c.PropertyName != null))
        {
            if (outputProps.Contains(rc.PropertyName))
                Console.WriteLine($"{et.Name}.{rc.PropertyName} on {sproc.Name} is both an output parameter and a result column.");
        }
    }
}

Prevention

When it happens

Trigger: On Insert/UpdateUsingStoredProcedure: .HasOutputParameter(p => p.Id) plus .HasResultColumn(p => p.Id) for the same property. Common when migrating from output parameters to result-set based sprocs without removing the old mapping.

Common situations: Switching a sproc from OUT parameter to SELECT-based return and leaving both calls in the fluent config; copy-paste of insert config to update config where one used OutputParameter and the other ResultColumn.

Related errors


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

Appendix: source

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

                    break;
                default:
                    Check.DebugFail("Unexpected stored procedure type: " + storeObjectIdentifier.StoreObjectType);
                    break;
            }
        }

        foreach (var resultColumn in sproc.ResultColumns)
        {
            if (resultColumn.PropertyName == null)
            {
                continue;
            }

            properties.Remove(resultColumn.PropertyName);

            if (!storeGeneratedProperties.Remove(resultColumn.PropertyName))
            {
                throw new InvalidOperationException(
                    RelationalStrings.StoredProcedureResultColumnParameterConflict(
                        entityType.DisplayName(), resultColumn.PropertyName, storeObjectIdentifier.DisplayName()));
            }
        }

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

        if (properties.Count > 0)
        {
            foreach (var property in properties.Values.ToList())
            {

View on GitHub (pinned to 3a2006ef56)