dotnet/efcore · error · InvalidOperationException
The property ' . ' is mapped to an output parameter of the…
Error message
The property '{entityType}.{property}' is mapped to an output parameter of the stored procedure '{sproc}', but it is also mapped to an output original value output parameter. A store-generated property can only be mapped to one output parameter. What it means
Thrown when a single store-generated property is mapped to TWO different non-input parameters of an insert/update sproc — one a normal output parameter and one an output-original-value parameter (ForOriginalValue differs). The validator first tries to remove the property from the storeGeneratedProperties set; if it was already consumed by an earlier output parameter, it scans sproc.Parameters for any other parameter with the same property name, different ForOriginalValue flag, and non-Input direction, and reports the conflict. Store-generated values may only flow back through one channel.
Solutions
- Keep only one output mapping for the store-generated property: prefer HasOutputParameter(p => p.Foo) and delete the duplicate HasOutputParameter(... forOriginalValue: true) for the same property.
- If you genuinely need the original value too, that property is not store-generated in the sense EF needs — reconfigure it as a regular concurrency token with HasOriginalValueParameter, not an output parameter.
- Inspect every parameter on the sproc mapping whose PropertyName equals the offending one and remove all but one with Direction != Input.
Example fix
// before
entityType.InsertUsingStoredProcedure("InsertOrder",
sp =>
{
sp.HasResultColumn(o => o.OrderId);
sp.HasOutputParameter(o => o.OrderId); // conflict: two outputs for OrderId
});
// after
entityType.InsertUsingStoredProcedure("InsertOrder",
sp =>
{
sp.HasResultColumn(o => o.OrderId);
}); Defensive patterns
Strategy: validation
Validate before calling
// Ensure each store-generated property has at most one non-input parameter mapping.
foreach (var et in model.GetEntityTypes())
{
foreach (var sproc in new[] { et.GetInsertStoredProcedure(), et.GetUpdateStoredProcedure() })
{
if (sproc == null) continue;
var outputsByProp = sproc.Parameters
.Where(p => p.Direction != System.Data.ParameterDirection.Input && p.PropertyName != null)
.GroupBy(p => p.PropertyName);
foreach (var g in outputsByProp.Where(g => g.Select(p => p.ForOriginalValue).Distinct().Count() > 1))
Console.WriteLine($"Property {g.Key} on {sproc.Name} has conflicting output mappings.");
}
} Prevention
- Keep all sproc read-back config in one fluent block per entity so duplicates are visually obvious.
- Prefer result columns over output parameters when the sproc returns a result set.
- Code-review sproc mappings whenever an entity gains a new store-generated property.
When it happens
Trigger: On an Insert/UpdateUsingStoredProcedure, calling both .HasOutputParameter(p => p.Id) and .HasOutputParameter(p => p.Id, forOriginalValue: true) (or two parameters with the same PropertyName but different ForOriginalValue). Mixing a result column for the same property with an output parameter also trips related checks.
Common situations: Wanting EF to capture both current value and original value of a store-generated column; accidentally registering the same property twice via fluent calls in different locations; refactor that moved an output parameter without removing the old mapping.
Related errors
- The entity type ' ' is mapped to the stored procedure ' '…
- The property ' . ' is mapped to an output parameter of the…
- The property ' . ' is mapped to a result column of the…
- A rows affected parameter, result column or return value…
- Both ' ' and ' ' are explicitly mapped to the stored…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/180d39cdf45df585.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:803
}
if (parameter.PropertyName == null)
{
continue;
}
switch (storeObjectIdentifier.StoreObjectType)
{
case StoreObjectType.InsertStoredProcedure:
case StoreObjectType.UpdateStoredProcedure:
if (parameter.Direction != ParameterDirection.Input
&& !storeGeneratedProperties.Remove(property!.Name))
{
if (sproc.Parameters.Any(p => p.PropertyName == property.Name
&& p.ForOriginalValue != parameter.ForOriginalValue
&& p.Direction != ParameterDirection.Input))
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureOutputParameterConflict(
entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
}
throw new InvalidOperationException(
RelationalStrings.StoredProcedureOutputParameterNotGenerated(
entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
}
break;
case StoreObjectType.DeleteStoredProcedure:
if (!property!.IsPrimaryKey()
&& !property.IsConcurrencyToken)
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureDeleteNonKeyProperty(
entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
}View on GitHub (pinned to 3a2006ef56)