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

  1. Pass the same stored value to HasComputedColumnSql on both properties.
  2. Decide on stored vs virtual once and apply it consistently across all entities sharing the column.
  3. 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

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


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)