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 not configured as store-generated. What it means
Thrown in the result-column switch for Insert and Update sprocs when the bound property is not in storeGeneratedProperties (RelationalModelValidator.cs:678-685). storeGeneratedProperties is computed at lines 633-640 as properties with ValueGenerated.OnAdd (insert) or ValueGenerated.OnUpdate (update). A result column implies the DB produces the value, so the property must be marked store-generated.
Solutions
- Mark the property store-generated to match the sproc type: .ValueGeneratedOnAdd() for insert result columns, .ValueGeneratedOnUpdate() (or .ValueGeneratedOnAddOrUpdate()) for update.
- If the property isn't actually DB-generated, remove the HasResultColumn binding and pass it as an input parameter instead.
- For computed columns use .ValueGeneratedOnAddOrUpdate() so they appear in both store-generated sets.
Example fix
// before
modelBuilder.Entity<Customer>()
.InsertUsingStoredProcedure("dbo.CustomerInsert", sp =>
{
sp.HasParameter(c => c.Name);
sp.HasResultColumn(c => c.CreatedAt); // not marked store-generated
});
// after
modelBuilder.Entity<Customer>(b =>
{
b.Property(c => c.CreatedAt).ValueGeneratedOnAdd();
b.InsertUsingStoredProcedure("dbo.CustomerInsert", sp =>
{
sp.HasParameter(c => c.Name);
sp.HasResultColumn(c => c.CreatedAt);
});
}); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in modelBuilder.Model.GetEntityTypes())
{
var insert = et.GetInsertStoredProcedure();
var update = et.GetUpdateStoredProcedure();
if (insert is not null)
{
var gen = et.GetProperties().Where(p => p.ValueGenerated.HasFlag(ValueGenerated.OnAdd)).Select(p => p.Name).ToHashSet();
foreach (var rc in insert.ResultColumns.Where(c => c.PropertyName is not null))
if (!gen.Contains(rc.PropertyName))
throw new InvalidOperationException($"Insert sproc result column '{rc.PropertyName}' on '{et.Name}' must be ValueGeneratedOnAdd.");
}
if (update is not null)
{
var gen = et.GetProperties().Where(p => p.ValueGenerated.HasFlag(ValueGenerated.OnUpdate)).Select(p => p.Name).ToHashSet();
foreach (var rc in update.ResultColumns.Where(c => c.PropertyName is not null))
if (!gen.Contains(rc.PropertyName))
throw new InvalidOperationException($"Update sproc result column '{rc.PropertyName}' on '{et.Name}' must be ValueGeneratedOnUpdate.");
}
} Try / catch
try { _ = ctx.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("not configured as store-generated"))
{
logger.LogError("Result-column property must be store-generated. {Msg}", ex.Message);
throw;
} Prevention
- Mark identity columns .ValueGeneratedOnAdd() and computed columns .ValueGeneratedOnAddOrUpdate() before binding them as result columns.
- Treat HasResultColumn as 'value produced by the DB' — never bind plain input columns to it.
- Validate the model after switching a property's value-generated setting.
When it happens
Trigger: Adding .HasResultColumn(x => x.UpdatedAt) to an Update sproc without marking AtUpdatedAt as ValueGenerated.OnUpdate (or .HasDatabaseGeneratedOption). Or binding a normal property as a result column expecting EF to read it back, without configuring value generation.
Common situations: Treating a regular column as a result column so EF reads it after save; forgetting .ValueGeneratedOnAdd()/OnUpdate() on identity/computed/timestamp columns when moving to sproc mapping.
Related errors
- Input parameter ' ' of insert stored procedure ' ' is…
- No property named ' ' found on the entity type ' '…
- The property ' . ' is mapped to a result column of the…
- The result column ' ' cannot be added to the stored…
- Both entity type ' ' and ' ' were configured to use ' '…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/d0f9904921ca1d97.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:682
if (!resultColumnNames.Add(resultColumn.Name))
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureDuplicateResultColumnName(
resultColumn.Name, storeObjectIdentifier.DisplayName()));
}
if (resultColumn.PropertyName == null)
{
continue;
}
switch (storeObjectIdentifier.StoreObjectType)
{
case StoreObjectType.InsertStoredProcedure:
case StoreObjectType.UpdateStoredProcedure:
if (!storeGeneratedProperties.ContainsKey(property.Name))
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureResultColumnNotGenerated(
entityType.DisplayName(), resultColumn.PropertyName, storeObjectIdentifier.DisplayName()));
}
break;
case StoreObjectType.DeleteStoredProcedure:
throw new InvalidOperationException(
RelationalStrings.StoredProcedureResultColumnDelete(
entityType.DisplayName(), resultColumn.PropertyName, storeObjectIdentifier.DisplayName()));
default:
Check.DebugFail("Unexpected stored procedure type: " + storeObjectIdentifier.StoreObjectType);
break;
}
}
var originalValueProperties = new Dictionary<string, IProperty>(properties);
var parameterNames = new HashSet<string>();
foreach (var parameter in sproc.Parameters)View on GitHub (pinned to 3a2006ef56)