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 computed values ('{value1}' and '{value2}').

What it means

Two properties sharing a column declare different computed-column SQL expressions via HasComputedColumnSql. Because the database can only compute one expression for the column, EF requires the expressions to match (compared case-insensitively). A mismatch would create an ambiguous migration.

Solutions

  1. Set the same HasComputedColumnSql expression (same text) on both properties.
  2. Remove the computed SQL from one side so both fall back to the same value.
  3. If the computations truly differ, remap one property to its own column.

Example fix

// before
modelBuilder.Entity<Order>().Property(o => o.Net).HasComputedColumnSql("[Total] - [Tax]");
modelBuilder.Entity<OrderSummary>().Property(s => s.Net).HasComputedColumnSql("[Total]-[Tax]");

// after
modelBuilder.Entity<Order>().Property(o => o.Net).HasComputedColumnSql("[Total] - [Tax]");
modelBuilder.Entity<OrderSummary>().Property(s => s.Net).HasComputedColumnSql("[Total] - [Tax]");
Defensive patterns

Strategy: validation

Validate before calling

foreach (var (col, props) in sharedColumnGroups)
{
    var sqls = props.Select(p => p.GetComputedColumnSql(storeObject) ?? "").Distinct(StringComparer.OrdinalIgnoreCase).ToList();
    if (sqls.Count > 1)
        Console.WriteLine($"Column {col} has conflicting computed-column SQL");
}

Try / catch

try { _ = db.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("different computed values")) { // align HasComputedColumnSql on both properties }

Prevention

When it happens

Trigger: ValidateCompatible() reads property.GetComputedColumnSql(storeObject) and duplicateProperty.GetComputedColumnSql(storeObject) (null coerced to empty string) and they are not equal under OrdinalIgnoreCase.

Common situations: Two entities table-split on a computed column where one specifies '[Total] - [Tax]' and the other '[Net]'; copy-paste of computed SQL with subtle casing/whitespace differences; scaffolded computed columns edited inconsistently.

Related errors


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

Appendix: source

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

                || (duplicateProperty.IsIndex() && duplicateProperty.GetContainingIndexes().Any(i => i.IsUnique))))
        {
            throw new InvalidOperationException(
                RelationalStrings.DuplicateColumnNameProviderTypeMismatch(
                    duplicateProperty.DeclaringType.DisplayName(),
                    duplicateProperty.Name,
                    property.DeclaringType.DisplayName(),
                    property.Name,
                    columnName,
                    storeObject.DisplayName(),
                    previousProviderType.ShortDisplayName(),
                    currentProviderType.ShortDisplayName()));
        }

        var currentComputedColumnSql = property.GetComputedColumnSql(storeObject) ?? "";
        var previousComputedColumnSql = duplicateProperty.GetComputedColumnSql(storeObject) ?? "";
        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(),

View on GitHub (pinned to 3a2006ef56)