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 data types ('{dataType1}' and '{dataType2}').

What it means

Two properties mapped to the same column have different explicit column types via GetColumnType (e.g. 'date' vs 'datetime', or 'bigint' vs 'int'). Because one physical column can only have one type, EF rejects the model rather than silently coercing. The comparison is case-insensitive.

Solutions

  1. Call HasColumnType("<same-type>") on both properties.
  2. Drop the explicit HasColumnType from one side so it derives from the type mapping and matches.
  3. Verify the two properties' ClrType are compatible and align the column type accordingly.
  4. If types really must differ, remap one property to a distinct column.

Example fix

// before
modelBuilder.Entity<Event>().Property(e => e.Occurred).HasColumnType("datetime");
modelBuilder.Entity<EventAudit>().Property(a => a.Occurred).HasColumnType("datetime2"); // shared

// after
modelBuilder.Entity<Event>().Property(e => e.Occurred).HasColumnType("datetime2");
modelBuilder.Entity<EventAudit>().Property(a => a.Occurred).HasColumnType("datetime2");
Defensive patterns

Strategy: validation

Validate before calling

foreach (var (col, props) in sharedColumnGroups)
{
    var types = props.Select(p => p.GetColumnType(storeObject)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
    if (types.Count > 1)
        Console.WriteLine($"Column {col} has conflicting column types: {string.Join(", ", types)}");
}

Try / catch

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

Prevention

When it happens

Trigger: ValidateCompatible() reads property.GetColumnType(storeObject) and duplicateProperty.GetColumnType(storeObject), and string.Equals(..., OrdinalIgnoreCase) returns false. Common when both sides call HasColumnType with different literals.

Common situations: Scaffolding a legacy schema where two entities overlapped on a column; mixed annotations vs fluent HasColumnType; an owned type's column type set explicitly while the owner uses the convention-driven type.

Related errors


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

Appendix: source

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

        }

        if (property.IsConcurrencyToken != duplicateProperty.IsConcurrencyToken)
        {
            throw new InvalidOperationException(
                RelationalStrings.DuplicateColumnNameConcurrencyTokenMismatch(
                    duplicateProperty.DeclaringType.DisplayName(),
                    duplicateProperty.Name,
                    property.DeclaringType.DisplayName(),
                    property.Name,
                    columnName,
                    storeObject.DisplayName()));
        }

        var currentTypeString = property.GetColumnType(storeObject);
        var previousTypeString = duplicateProperty.GetColumnType(storeObject);
        if (!string.Equals(currentTypeString, previousTypeString, StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException(
                RelationalStrings.DuplicateColumnNameDataTypeMismatch(
                    duplicateProperty.DeclaringType.DisplayName(),
                    duplicateProperty.Name,
                    property.DeclaringType.DisplayName(),
                    property.Name,
                    columnName,
                    storeObject.DisplayName(),
                    previousTypeString,
                    currentTypeString));
        }

        var typeMapping = property.GetRelationalTypeMapping();
        var duplicateTypeMapping = duplicateProperty.GetRelationalTypeMapping();
        var currentProviderType = typeMapping.Converter?.ProviderClrType.UnwrapNullableType()
            ?? typeMapping.ClrType;
        var previousProviderType = duplicateTypeMapping.Converter?.ProviderClrType.UnwrapNullableType()
            ?? duplicateTypeMapping.ClrType;
        if (currentProviderType != previousProviderType

View on GitHub (pinned to 3a2006ef56)