{"record":{"id":"8373bde312764809","repo":"dotnet/efcore","slug":"named-default-constraints-cannot-be-used-with-tpc","errorCode":null,"errorMessage":"Named default constraints cannot be used with TPC or entity splitting if they result in non-unique constraint names. Constraint name: '{constraintNameCandidate}'.","messagePattern":"Named default constraints cannot be used with TPC or entity splitting if they result in non-unique constraint names\\. Constraint name: '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs","lineNumber":768,"sourceCode":"\n    private static string? TryUniquifyDefaultConstraint(\n        IConventionProperty property,\n        string constraintName,\n        string? schema,\n        Dictionary<(string, string?), (IConventionProperty, StoreObjectIdentifier)> defaultConstraints,\n        in StoreObjectIdentifier storeObject,\n        int maxLength)\n    {\n        var mappedTables = property.GetMappedStoreObjects(StoreObjectType.Table);\n        if (mappedTables.Count() > 1)\n        {\n            // For TPC and some entity splitting scenarios we end up with multiple tables having to define the constraint.\n            // Since constraint name has to be unique, we can't keep the same name for all\n            // Disabling this scenario until we have better way to configure the constraint name\n            // see issue #27970\n            if (property.GetDefaultConstraintNameConfigurationSource() == null)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.ImplicitDefaultNamesNotSupportedForTpcWhenNamesClash(constraintName));\n            }\n\n            throw new InvalidOperationException(\n                RelationalStrings.ExplicitDefaultConstraintNamesNotSupportedForTpc(constraintName));\n        }\n\n        if (property.Builder.CanSetAnnotation(RelationalAnnotationNames.DefaultConstraintName, null))\n        {\n            constraintName = Uniquifier.Uniquify(constraintName, defaultConstraints, n => (n, schema), maxLength);\n            property.Builder.HasAnnotation(RelationalAnnotationNames.DefaultConstraintName, constraintName);\n            return constraintName;\n        }\n\n        return null;\n    }\n\n    private void UniquifyTriggerNames(","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs#L750-L786","documentation":"Thrown by SharedTableConvention.TryUniquifyDefaultConstraint (SharedTableConvention.cs:766-770) when a property is mapped to more than one table (as in TPC inheritance or entity splitting) and the default constraint name has NO explicit configuration source (it's auto-generated/implicit). Since the constraint name must be unique per table but the implicit name is shared, EF cannot safely uniquify it. This is tracked as issue #27970 and is a known limitation.","triggerScenarios":"Using TPC inheritance (UseTpcMapping) or entity splitting where an entity has a property with a default value (or computed default), the property maps to multiple tables, and the default constraint name was not explicitly set via HasDefaultValue(...).HasDefaultValueConstraintName(\"...\").","commonSituations":"Switching from TPH/TPT to TPC with properties that have default values. Entity splitting with default values. EF auto-generates default constraint names that clash across the multiple tables in TPC.","solutions":["Explicitly set a unique default constraint name per table using HasDefaultValue(value, defaultValueSql: null).HasDefaultValueConstraintName(\"DF_TableName_Col\") for each mapped table.","Remove the default value from properties involved in TPC/entity splitting, or set defaults at the database level outside EF.","Switch from TPC to TPH or TPT if possible, where this limitation does not apply."],"exampleFix":"// before: TPC with implicit default constraint names that clash\nmodelBuilder.Entity<Base>().UseTpcMappingStrategy();\nmodelBuilder.Entity<Base>().Property(b => b.Status).HasDefaultValue(0);\n\n// after: explicitly name the default constraint uniquely per table\nmodelBuilder.Entity<DerivedA>().ToTable(\"DerivedA\", t =>\n    t.Property(b => b.Status).HasDefaultValue(0).HasDefaultValueConstraintName(\"DF_DerivedA_Status\"));\nmodelBuilder.Entity<DerivedB>().ToTable(\"DerivedB\", t =>\n    t.Property(b => b.Status).HasDefaultValue(0).HasDefaultValueConstraintName(\"DF_DerivedB_Status\"));","handlingStrategy":"validation","validationCode":"// Detect TPC/entity-splitting properties with implicit default constraint names mapped to multiple tables.\nforeach (var et in modelBuilder.Model.GetEntityTypes())\n{\n    foreach (var prop in et.GetDeclaredProperties())\n    {\n        if (prop.GetMappedStoreObjects(StoreObjectType.Table).Count() <= 1) continue;\n        if (prop.GetDefaultValue() != null && prop.GetDefaultConstraintNameConfigurationSource() == null)\n            Console.WriteLine($\"Property {et.DisplayName()}.{prop.Name} maps to multiple tables with a default but no explicit constraint name — TPC limitation.\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid HasDefaultValue on properties that participate in TPC or entity splitting.","If defaults are needed in TPC, apply them via raw migration SQL with unique constraint names per table.","Add a model validation test that warns about multi-table default constraints."],"tags":["default-constraint","tpc","entity-splitting","convention"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}