dotnet/efcore · error · InvalidOperationException

'{entityType1}.{property1}' and '{entityType2}.{property2}'

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 specify different store column types via GetColumnType (e.g. 'varchar(50)' vs 'nvarchar(100)'). The validator compares column type strings case-insensitively and aborts if they differ. Thrown from ValidateCompatible.

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 dbf9771522)

Solutions

  1. Set HasColumnType to the identical string on both properties (case-insensitive match is required).
  2. If the types genuinely differ, rename one column with HasColumnName.
  3. Remove the explicit HasColumnType so both inherit the provider default for the CLR type.

Example fix

// before
modelBuilder.Entity<Student>().Property(s => s.Code).HasColumnType("varchar(20)");
modelBuilder.Entity<Teacher>().Property(t => t.Code).HasColumnType("nvarchar(20)");
// after
modelBuilder.Entity<Student>().Property(s => s.Code).HasColumnType("varchar(20)");
modelBuilder.Entity<Teacher>().Property(t => t.Code).HasColumnType("varchar(20)");
Defensive patterns

Strategy: validation

Validate before calling

using (var ctx = new MyContext()) { ctx.Model.ToDebugString(); }
var a = ctx.Model.FindEntityType(typeof(Student))!.FindProperty("Code")!.GetColumnType();
var b = ctx.Model.FindEntityType(typeof(Teacher))!.FindProperty("Code")!.GetColumnType();
Debug.Assert(string.Equals(a, b, StringComparison.OrdinalIgnoreCase), $"ColumnType mismatch: {a} vs {b}");

Try / catch

try { using var ctx = new MyContext(); _ = ctx.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("different data types"))
{ log.Error("Column-type mismatch on shared column: {Msg}", ex.Message); throw; }

Prevention

When it happens

Trigger: Sibling TPH types calling HasColumnType("varchar(50)") and HasColumnType("nvarchar(100)") on a same-named property; an owned entity and owner setting explicit types that don't match; table splitting where one side forces a custom column type.

Common situations: One team uses a custom column type for a Code property (e.g. 'citext') while another uses plain text; refactoring a property to a domain-specific type without updating siblings; mixing [Column(TypeName=...)] annotations with Fluent HasColumnType on different entities.

Related errors


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