dotnet/efcore · error · InvalidOperationException

The entity type ' ' is mapped to the stored procedure ' '…

Error message

The entity type '{entityType}' is mapped to the stored procedure '{sproc}', however the store-generated properties {properties} are not mapped to any output parameter or result column.

What it means

Thrown at the end of sproc validation when storeGeneratedProperties (the set of properties EF expects the database to populate) still has entries after all parameters and result columns were processed. The validator treats it as an explicit contract: every store-generated property on the entity must be reflected back through either an output parameter or a result column of the mapped sproc.

Solutions

  1. Add an output parameter or result column for each listed property: .HasResultColumn(p => p.Id), .HasOutputParameter(p => p.UpdatedAt).
  2. If the property should not be store-generated when using sprocs, remove the ValueGeneratedOnAdd/HasComputedColumnSql/HasDefaultValueSql configuration so it leaves the storeGeneratedProperties set.
  3. Verify the listed properties are the ones you actually expect; if a derived-type generated property is listed, map it on the derived sproc or exclude it from the inheritance hierarchy's generated set.

Example fix

// before
builder.Property(o => o.OrderId).ValueGeneratedOnAdd();
builder.Property(o => o.CreatedAt).HasDefaultValueSql("GETUTCDATE()");
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp => sp.HasParameter(o => o.CustomerId));
// -> error: OrderId, CreatedAt are generated but unmapped

// after
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp =>
    {
        sp.HasParameter(o => o.CustomerId);
        sp.HasResultColumn(o => o.OrderId);
        sp.HasResultColumn(o => o.CreatedAt);
    });
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in model.GetEntityTypes())
{
    var generated = et.GetProperties()
        .Where(p => p.ValueGenerated != Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.Never).ToList();
    foreach (var sproc in new[] { et.GetInsertStoredProcedure(), et.GetUpdateStoredProcedure() })
    {
        if (sproc == null) continue;
        var mapped = sproc.Parameters
            .Where(p => p.Direction != System.Data.ParameterDirection.Input && p.PropertyName != null)
            .Select(p => p.PropertyName)
            .Concat(sproc.ResultColumns.Where(c => c.PropertyName != null).Select(c => c.PropertyName))
            .ToHashSet();
        foreach (var g in generated.Where(g => !mapped.Contains(g.Name)))
            Console.WriteLine($"Store-generated {et.Name}.{g.Name} is not mapped to an output of {sproc.Name}.");
    }
}

Prevention

When it happens

Trigger: An entity has ValueGeneratedOnAdd/ValueGeneratedOnUpdate/HasDefaultValueSql/HasComputedColumnSql properties, but its Insert/UpdateUsingStoredProcedure mapping has no corresponding output parameter or result column. The sproc will silently fail to populate them, so EF refuses the model.

Common situations: Adding an identity/computed/timestamp column to the entity after the sproc mapping was written; using table-per-hierarchy where some generated columns belong only to derived types not yet mapped to the sproc.

Related errors


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

Appendix: source

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

        {
            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())
            {
                switch (storeObjectIdentifier.StoreObjectType)
                {
                    case StoreObjectType.InsertStoredProcedure:
                        if ((property.ValueGenerated & ValueGenerated.OnAdd) == 0
                            && property.GetBeforeSaveBehavior() != PropertySaveBehavior.Save)
                        {
                            properties.Remove(property.Name);
                        }

View on GitHub (pinned to 3a2006ef56)