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 provider types ('{type1}' and '{type2}').

What it means

Two properties sharing a column resolve to different provider CLR types, AND at least one of them is part of a key, foreign key, or unique index. For key/FK/unique-index columns the provider type must match exactly because it drives the index definition and join semantics. Non-key shared columns with differing provider types are tolerated (a value converter is allowed there).

Solutions

  1. Make the ClrType of both key/FK/unique-index properties identical.
  2. If a value converter is involved, ensure both sides convert to the same provider type.
  3. Remove the column from key / FK / unique-index duty on one side if the converter types must differ.
  4. Remap one of the properties to a separate column.

Example fix

// before
modelBuilder.Entity<Tenant>().Property(t => t.Id).HasConversion<Guid>();
modelBuilder.Entity<TenantConfig>().Property(c => c.Id).HasConversion<string>(); // shared PK column

// after
modelBuilder.Entity<Tenant>().Property(t => t.Id).HasConversion<Guid>();
modelBuilder.Entity<TenantConfig>().Property(c => c.Id).HasConversion<Guid>();
Defensive patterns

Strategy: validation

Validate before calling

foreach (var (col, props) in sharedColumnGroups.Where(g => g.Value.Any(p => p.IsKey() || p.IsForeignKey() || (p.IsIndex() && p.GetContainingIndexes().Any(i => i.IsUnique)))))
{
    var providerTypes = props.Select(p =>
    {
        var m = p.FindRelationalMapping() ?? p.GetTypeMapping();
        return m.Converter?.ProviderClrType.UnwrapNullableType() ?? m.ClrType;
    }).Distinct().ToList();
    if (providerTypes.Count > 1)
        Console.WriteLine($"Key/FK/unique-index column {col} has conflicting provider types");
}

Try / catch

try { _ = db.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("different provider types")) { // unify the value converter / CLR type of the key or FK column }

Prevention

When it happens

Trigger: ValidateCompatible() resolves provider types via typeMapping.Converter?.ProviderClrType ?? ClrType and, when they differ, throws only if any of: property/duplicateProperty.IsKey(), IsForeignKey(), or is part of a unique index. The check intentionally permits converter differences on plain columns.

Common situations: A shared primary key column where one side uses Guid and the other string; an FK column shared between two entities using different value converters; TPT where a discriminator-derived key column has incompatible converter types.

Related errors


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

Appendix: source

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

                    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
            && (property.IsKey()
                || duplicateProperty.IsKey()
                || property.IsForeignKey()
                || duplicateProperty.IsForeignKey()
                || (property.IsIndex() && property.GetContainingIndexes().Any(i => i.IsUnique))
                || (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(),

View on GitHub (pinned to 3a2006ef56)