{"record":{"id":"c6c9a303812d6911","repo":"dotnet/efcore","slug":"using-methodname-on-dbset-of-entitytype-is","errorCode":null,"errorMessage":"Using '{methodName}' on DbSet of '{entityType}' is not supported since '{entityType}' is part of hierarchy and does not contain a discriminator property.","messagePattern":"Using '(.+?)' on DbSet of '(.+?)' is not supported since '(.+?)' is part of hierarchy and does not contain a discriminator property\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs","lineNumber":192,"sourceCode":"        return queryableSource.Provider.CreateQuery<TEntity>(\n            GenerateFromSqlQueryRoot(\n                queryableSource,\n                sql.Format,\n                sql.GetArguments()));\n    }\n\n    private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot(\n        IQueryable source,\n        string sql,\n        object?[] arguments,\n        [CallerMemberName] string memberName = null!)\n    {\n        var entityQueryRootExpression = (EntityQueryRootExpression)source.Expression;\n\n        var entityType = entityQueryRootExpression.EntityType;\n        return (entityType.BaseType != null || entityType.GetDirectlyDerivedTypes().Any())\n            && entityType.FindDiscriminatorProperty() == null\n                ? throw new InvalidOperationException(\n                    RelationalStrings.MethodOnNonTphRootNotSupported(memberName, entityType.DisplayName()))\n                : new FromSqlQueryRootExpression(\n                    entityQueryRootExpression.QueryProvider!,\n                    entityType,\n                    sql,\n                    Expression.Constant(arguments));\n    }\n\n    #endregion\n\n    #region SplitQuery\n\n    /// <summary>\n    ///     Returns a new query which is configured to load the collections in the query results in a single database query.\n    /// </summary>\n    /// <remarks>\n    ///     <para>\n    ///         This behavior generally guarantees result consistency in the face of concurrent updates","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs#L174-L210","documentation":"GenerateFromSqlQueryRoot (RelationalQueryableExtensions.cs:192), used by FromSql/FromSqlRaw/FromSqlInterpolated, throws when the target entity type is part of an inheritance hierarchy (has a base type or derived types) but has no discriminator property. FromSql over DbSet needs a single concrete row-to-type mapping; without a discriminator EF cannot decide which hierarchy member each row represents, so it only supports TPH roots with a discriminator.","triggerScenarios":"Calling context.Set<DerivedEntity>().FromSqlRaw(...) or FromSqlInterpolated on a DbSet whose entity is in a TPT/TPC hierarchy, or a TPH hierarchy where the discriminator was removed/misconfigured. Also triggers when calling FromSql on a derived type rather than the hierarchy root.","commonSituations":"TPT or TPC hierarchies (no shared discriminator); mapped a discriminator but later removed it; calling FromSql on a derived entity instead of the base; hierarchy recently refactored from TPH to TPT.","solutions":["Call FromSql on the hierarchy root DbSet and let EF route rows by discriminator (requires TPH with a configured discriminator).","If using TPT/TPC, switch to a plain SQL projection (e.g. context.Set<DerivedEntity>().FromSqlRaw on a TVF/view is not supported either) - instead execute raw SQL via ADO.NET or use a keyless entity/SQL query mapping.","Ensure the discriminator is configured: modelBuilder.Entity<Base>().HasDiscriminator(b => b.Type) and that the entity is the TPH root.","If you must target a derived type only, map a separate keyless entity or a defining query backed by raw SQL."],"exampleFix":"// before (TPT/TPC, derived type)\nvar managers = context.Set<Manager>().FromSqlRaw(\"SELECT * FROM Managers\").ToList(); // throws\n\n// after - query the root in a TPH hierarchy with discriminator\nvar managers = context.Employees\n    .FromSqlRaw(\"SELECT * FROM Employees WHERE Discriminator = 'Manager'\")\n    .OfType<Manager>().ToList();","handlingStrategy":"validation","validationCode":"IEntityType entityType = context.Model.FindEntityType(typeof(TEntity))!;\nbool isHierarchyRoot = entityType.BaseType == null;\nbool hasDiscriminator = entityType.FindDiscriminatorProperty() != null;\nbool inHierarchy = entityType.BaseType != null || entityType.GetDerivedTypes().Any();\nif (inHierarchy && !hasDiscriminator)\n{\n    // FromSql on this DbSet will throw; query the root or avoid FromSql.\n}","typeGuard":"static bool SupportsFromSql<T>(IModel model) where T : class\n{\n    var et = model.FindEntityType(typeof(T))!;\n    var inHierarchy = et.BaseType != null || et.GetDerivedTypes().Any();\n    return !inHierarchy || et.FindDiscriminatorProperty() != null;\n}","tryCatchPattern":null,"preventionTips":["Call FromSql on the hierarchy root, not on derived DbSets.","Use TPH with a configured discriminator when raw-SQL entry points are needed.","Check the discriminator exists before composing raw SQL in shared code."],"tags":["inheritance","fromsql","discriminator","tpt","tpc"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}