{"record":{"id":"8b4c7347a7ce1ea8","repo":"dotnet/efcore","slug":"the-element-type-of-the-result-of-dbfunction-i","errorCode":null,"errorMessage":"The element type of the result of '{dbFunction}' is mapped to '{entityType}'. This is not supported since '{entityType}' is part of hierarchy but does not contain a discriminator property. Only TPH hierarchies can be mapped to a TVF.","messagePattern":"The element type of the result of '(.+?)' is mapped to '(.+?)'\\. This is not supported since '(.+?)' is part of hierarchy but does not contain a discriminator property\\. Only TPH hierarchies can be mapped to a TVF\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":397,"sourceCode":"                || ((IConventionModel)model).IsOwned(elementType)\n                || (entityType == null && model.GetEntityTypes().Any(e => e.ClrType == elementType)))\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.DbFunctionInvalidIQueryableOwnedReturnType(\n                        dbFunction.ModelName, elementType.ShortDisplayName()));\n            }\n\n            if (entityType == null)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.DbFunctionInvalidReturnEntityType(\n                        dbFunction.ModelName, dbFunction.ReturnType.ShortDisplayName(), elementType.ShortDisplayName()));\n            }\n\n            if ((entityType.BaseType != null || entityType.GetDerivedTypes().Any())\n                && entityType.FindDiscriminatorProperty() == null)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.TableValuedFunctionNonTph(dbFunction.ModelName, entityType.DisplayName()));\n            }\n        }\n\n        foreach (var parameter in dbFunction.Parameters)\n        {\n            if (parameter.TypeMapping == null)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.DbFunctionInvalidParameterType(\n                        parameter.Name,\n                        dbFunction.ModelName,\n                        parameter.ClrType.ShortDisplayName()));\n            }\n        }\n    }\n\n    /// <summary>","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L379-L415","documentation":"ValidateDbFunction (RelationalModelValidator.cs:394-399) throws for a non-scalar DbFunction (TVF) whose returned entity type is part of an inheritance hierarchy but has no discriminator property. A TVF result is a flat row set; EF can only route those rows to hierarchy members via a discriminator (TPH). TPT/TPC hierarchies or hierarchies lacking a discriminator cannot be the row type of a TVF, so the function is rejected.","triggerScenarios":"Mapping a DbFunction returning IQueryable<T> where T is in a TPT/TPC hierarchy, or a TPH hierarchy whose discriminator was removed/misconfigured. Thrown at model validation.","commonSituations":"TPT/TPC inheritance combined with TVF mapping; hierarchy discriminator removed while a TVF still targets the hierarchy; refactoring inheritance strategy without updating DbFunctions.","solutions":["Switch the hierarchy to TPH with a configured discriminator (modelBuilder.Entity<Base>().HasDiscriminator(...)) so the TVF rows can be classified.","Return a flat non-hierarchical entity (keyless DTO) from the TVF and map hierarchy members separately.","Remove the DbFunction mapping if the hierarchy cannot use TPH and map the query another way."],"exampleFix":"// before - TPT/TPC hierarchy as TVF row type\npublic IQueryable<Employee> EmployeesInDept(int deptId) => null!;\n// Person -> Employee inheritance is TPT (no discriminator)\nmodelBuilder.HasDbFunction(() => EmployeesInDept(default)); // throws\n\n// after - TPH with discriminator supports the TVF\nmodelBuilder.Entity<Person>().HasDiscriminator(p => p.Type).HasValue<Employee>(\"E\");\nmodelBuilder.HasDbFunction(() => EmployeesInDept(default));","handlingStrategy":"validation","validationCode":"foreach (var fn in context.Model.GetDbFunctions())\n{\n    if (!fn.IsScalar)\n    {\n        var elementType = fn.ReturnType.GetGenericArguments()[0];\n        var et = context.Model.FindEntityType(elementType);\n        if (et != null\n            && (et.BaseType != null || et.GetDerivedTypes().Any())\n            && et.FindDiscriminatorProperty() == null)\n        {\n            // will throw - use TPH with a discriminator or a non-hierarchical row type.\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only map TVFs to TPH hierarchies that have a discriminator.","Return a flat keyless entity from TVFs when inheritance isn't TPH.","Re-audit DbFunctions when changing inheritance strategy."],"tags":["dbfunction","tvf","inheritance","discriminator","model-validation"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}