dotnet/efcore · error · InvalidOperationException
' ' is mapped to the view ' ' while ' ' is mapped to the…
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
Thrown inside ValidateTphMapping when a derived type resolves to a different View StoreObjectIdentifier than the root. TPH requires all types in the hierarchy to share the same view; mapping a derived type to another view is rejected.
Solutions
- Remove the ToView override on the derived type so it uses the root's view.
- Switch the hierarchy to TPT/TPC if separate views are intended.
- Map the root to the same view as the derived types.
Example fix
// before
modelBuilder.Entity<Person>().ToView("v_People");
modelBuilder.Entity<Customer>().ToView("v_Customers"); // throws 433
// after (separate views -> TPT)
modelBuilder.UseTptMappingStrategy();
modelBuilder.Entity<Person>().ToView("v_People");
modelBuilder.Entity<Customer>().ToView("v_Customers"); Defensive patterns
Strategy: validation
Validate before calling
foreach (var root in modelBuilder.Model.GetEntityTypes().Where(t => t.BaseType == null))
{
if (root.FindDiscriminatorProperty() == null) continue;
var rootSo = StoreObjectIdentifier.Create(root, StoreObjectType.View);
if (rootSo == null) continue;
foreach (var et in root.GetDerivedTypes())
{
var so = StoreObjectIdentifier.Create(et, StoreObjectType.View);
if (so != null && so.Value != rootSo.Value)
throw new InvalidOperationException($"{et.DisplayName()} view {so.Value.DisplayName()} differs from root view {rootSo.Value.DisplayName()} (TPH).");
}
} Prevention
- In TPH, do not call ToView on derived types.
- Switch to TPT/TPC if separate views are intended.
- Add a model test asserting view consistency across a TPH hierarchy.
When it happens
Trigger: A TPH hierarchy where a derived type calls ToView("OtherView") (or is otherwise mapped to a different view than the root).
Common situations: Adding ToView on a derived type under TPH; layered read-model views per type; refactor that diverged view names.
Related errors
- Both ' ' and ' ' are explicitly mapped to the stored…
- Both ' ' and ' ' are mapped to the view ' '. All the entity…
- ' ' is mapped to the database function ' ' while ' ' is…
- ' ' is mapped to the stored procedure ' ' while ' ' is…
- ' ' is mapped to the table ' ' while ' ' is mapped to the…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/5ceb51bf148cb73f.
Report an issue: GitHub.
Appendix: 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 3a2006ef56)