dotnet/efcore · error · InvalidOperationException
' . ' and ' . ' are both mapped to column ' ' in ' ', but…
Error message
'{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured to use different stored computed column settings ('{value1}' and '{value2}'). What it means
Two properties sharing a column are computed columns but disagree on the 'stored' flag (GetIsStored). Stored computed columns are materialized on write; virtual ones are computed on read. The provider can only honor one setting per column, so EF rejects the model when they conflict.
Solutions
- Pass the same stored value to HasComputedColumnSql on both properties.
- Decide on stored vs virtual once and apply it consistently across all entities sharing the column.
- Remap one property to a distinct column if the stored requirement genuinely differs.
Example fix
// before
modelBuilder.Entity<Balance>().Property(b => b.Total).HasComputedColumnSql("[Credit]-[Debit]", stored: true);
modelBuilder.Entity<BalanceAudit>().Property(a => a.Total).HasComputedColumnSql("[Credit]-[Debit]", stored: false);
// after
modelBuilder.Entity<Balance>().Property(b => b.Total).HasComputedColumnSql("[Credit]-[Debit]", stored: true);
modelBuilder.Entity<BalanceAudit>().Property(a => a.Total).HasComputedColumnSql("[Credit]-[Debit]", stored: true); Defensive patterns
Strategy: validation
Validate before calling
foreach (var (col, props) in sharedColumnGroups)
{
var stored = props.Select(p => p.GetIsStored(storeObject)).Distinct().ToList();
if (stored.Count > 1)
Console.WriteLine($"Column {col} has conflicting stored-computed settings");
} Try / catch
try { _ = db.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("different stored computed column settings")) { // align the stored argument of HasComputedColumnSql on both properties } Prevention
- Decide stored vs virtual once per computed column and apply it consistently.
- Be aware that 'stored' is provider-specific (PERSISTED on SQL Server).
- Smoke-test the model at startup.
When it happens
Trigger: ValidateCompatible() reads property.GetIsStored(storeObject) and duplicateProperty.GetIsStored(storeObject) (both nullable bools) and they are not equal. One property called HasComputedColumnSql(sql, stored: true) and the other stored: false (or left null).
Common situations: One entity configured the computed column as PERSISTED (stored) and the other as virtual; scaffolded model where one side lost the stored flag during manual edits; SQL Server-specific migrations ported to another provider.
Related errors
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e160f930f6740f95.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:1692
if (!currentComputedColumnSql.Equals(previousComputedColumnSql, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(
RelationalStrings.DuplicateColumnNameComputedSqlMismatch(
duplicateProperty.DeclaringType.DisplayName(),
duplicateProperty.Name,
property.DeclaringType.DisplayName(),
property.Name,
columnName,
storeObject.DisplayName(),
previousComputedColumnSql,
currentComputedColumnSql));
}
var currentStored = property.GetIsStored(storeObject);
var previousStored = duplicateProperty.GetIsStored(storeObject);
if (currentStored != previousStored)
{
throw new InvalidOperationException(
RelationalStrings.DuplicateColumnNameIsStoredMismatch(
duplicateProperty.DeclaringType.DisplayName(),
duplicateProperty.Name,
property.DeclaringType.DisplayName(),
property.Name,
columnName,
storeObject.DisplayName(),
previousStored,
currentStored));
}
var hasDefaultValue = property.TryGetDefaultValue(storeObject, out var currentDefaultValue);
var duplicateHasDefaultValue = duplicateProperty.TryGetDefaultValue(storeObject, out var previousDefaultValue);
if ((hasDefaultValue
|| duplicateHasDefaultValue)
&& !Equals(currentDefaultValue, previousDefaultValue))
{
currentDefaultValue = GetDefaultColumnValue(property, storeObject);View on GitHub (pinned to 3a2006ef56)