dotnet/efcore · error · InvalidOperationException
'{entityType}' is mapped to the view '{view}' while '{otherE
Error message
'{entityType}' is mapped to the view '{view}' while '{otherEntityType}' is mapped to the view '{otherView}'. Map all the entity types in the hierarchy to the same view, or remove the discriminator and map them all to different views. See https://go.microsoft.com/fwlink/?linkid=2130430 for more information. What it means
ValidateTphMapping for StoreObjectType.View: identical rule to TphTableMismatch but for views. A TPH hierarchy must map all types to the same view; a derived type resolving to a different view StoreObjectIdentifier than the root is rejected.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2335
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureTphDuplicate(
entityType.DisplayName(), rootEntityType.DisplayName(), rootId?.DisplayName()));
}
}
continue;
}
switch (storeObjectType)
{
case StoreObjectType.Table:
throw new InvalidOperationException(
RelationalStrings.TphTableMismatch(
entityType.DisplayName(), entityId.Value.DisplayName(),
rootEntityType.DisplayName(), rootId?.DisplayName()));
case StoreObjectType.View:
throw new InvalidOperationException(
RelationalStrings.TphViewMismatch(
entityType.DisplayName(), entityId.Value.DisplayName(),
rootEntityType.DisplayName(), rootId?.DisplayName()));
case StoreObjectType.Function:
throw new InvalidOperationException(
RelationalStrings.TphDbFunctionMismatch(
entityType.DisplayName(), entityId.Value.DisplayName(),
rootEntityType.DisplayName(), rootId?.DisplayName()));
case StoreObjectType.InsertStoredProcedure:
case StoreObjectType.DeleteStoredProcedure:
case StoreObjectType.UpdateStoredProcedure:
throw new InvalidOperationException(
RelationalStrings.TphStoredProcedureMismatch(
entityType.DisplayName(), entityId.Value.DisplayName(),
rootEntityType.DisplayName(), rootId?.DisplayName()));
}
}
}View on GitHub (pinned to dbf9771522)
Solutions
- Drop the per-derived .ToView so all types share the root view.
- Remove the discriminator to switch to TPT, then map each type to its own view.
- Point the derived type at the SAME view name/schema as the root.
Example fix
// before
modelBuilder.Entity<Base>().HasDiscriminator(b => b.Kind).ToView("v_Base");
modelBuilder.Entity<Derived>().ToView("v_Derived");
// after
modelBuilder.Entity<Base>().HasDiscriminator(b => b.Kind).ToView("v_Base");
// derived omitted, inherits root view Defensive patterns
Strategy: validation
Validate before calling
bool TphAllTypesSameView(DbContext context)
{
foreach (var root in context.Model.GetEntityTypes()
.Where(e => e.BaseType == null && e.FindDiscriminatorProperty() != null && e.GetDerivedTypes().Any()))
{
var rootView = StoreObjectIdentifier.Create(root, StoreObjectType.View);
if (rootView is null) continue;
foreach (var d in root.GetDerivedTypes())
if (StoreObjectIdentifier.Create(d, StoreObjectType.View) is { } dv && dv != rootView) return false;
}
return true;
} Try / catch
try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("mapped to the view", StringComparison.Ordinal) && ex.Message.Contains("same view", StringComparison.Ordinal))
{
throw new InvalidOperationException("A TPH hierarchy must keep all types on one view. Remove the derived .ToView or drop the discriminator for TPT.", ex);
} Prevention
- In TPH, do not set a different .ToView on derived types.
- Use TPT (no discriminator) when each type needs its own view.
- Smoke-test the model in your test suite.
When it happens
Trigger: Root has a discriminator (TPH) and a ToView, and a derived type was given a different .ToView("OtherView"), so its StoreObjectIdentifier differs from rootId.
Common situations: Read-only TPH model where one derived type was pointed at a different view; scaffolding views then enabling a discriminator.
Related errors
- Both '{entityType}' and '{otherEntityType}' are mapped to th
- Both '{entityType}' and '{otherEntityType}' are explicitly
- '{entityType}' is mapped to the table '{table}' while '{othe
- '{entityType}' is mapped to the database function '{function
- '{entityType}' is mapped to the stored procedure '{sproc}' w
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/5ceb51bf148cb73f.
Report an issue: GitHub.