You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
UserId=table.Column<string>("varchar(32)", nullable: false), // ❌ Foreign key after created_at/modified_at, use text not varchar
92
99
},
93
100
constraints: table=>
94
101
{
95
-
table.PrimaryKey("PrimaryKey_UserPreference", i=>i.Id); // ❌ Incorrect PK naming, variable should be x not i
96
-
table.ForeignKey("ForeignKey_UserPreference_User", x=>x.UserId, "Users", "Id"); // ❌ Incorrect FK naming
102
+
table.PrimaryKey("PK_UserPreference", i=>i.Id); // ❌ PascalCase PK naming, variable should be x not i
103
+
table.ForeignKey("FK_UserPreference_User", x=>x.UserId, "Users", "Id"); // ❌ PascalCase FK naming
97
104
}
98
105
);
99
106
}
100
-
107
+
101
108
protectedoverridevoidDown(MigrationBuildermigrationBuilder) // ❌ DON'T: Create a down method
102
109
{
103
110
migrationBuilder.DropTable("UserPreference");
104
111
}
105
112
}
106
113
```
107
114
108
-
### Example 2 - Determining column sizes from validators
115
+
### Example 2 - Filtered indexes and data migrations
116
+
117
+
```csharp
118
+
// ✅ DO: Use PostgreSQL WHERE clause syntax for filtered indexes
119
+
migrationBuilder.CreateIndex("ix_users_tenant_id_email", "users", ["tenant_id", "email"], unique: true, filter: "deleted_at IS NULL");
120
+
migrationBuilder.CreateIndex("ix_subscriptions_stripe_customer_id", "subscriptions", "stripe_customer_id", unique: true, filter: "stripe_customer_id IS NOT NULL");
121
+
122
+
// ❌ DON'T: Use SQL Server bracket notation
123
+
migrationBuilder.CreateIndex("IX_Users_TenantId_Email", "Users", ["TenantId", "Email"], unique: true, filter: "[DeletedAt] IS NULL");
124
+
```
109
125
110
126
```csharp
127
+
// ✅ DO: Use text for string columns, enforce length in validators
Copy file name to clipboardExpand all lines: .claude/rules/backend/strongly-typed-ids.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ Guidelines for implementing strongly typed IDs in the backend, covering type saf
11
11
12
12
1. Use strongly typed IDs to provide type safety and prevent mixing different ID types, improving readability and maintainability
13
13
2. By default, use `StronglyTypedUlid<T>` as the base class—it provides chronological ordering and includes a prefix for easy recognition (e.g., `usr_01JMVAW4T4320KJ3A7EJMCG8R0`)
14
-
3. Use the `[IdPrefix]` attribute with a short prefix (max 5 characters)—ULIDs are 26 chars, plus 5-char prefix and underscore = 32 chars for varchar(32)
14
+
3. Use the `[IdPrefix]` attribute with a short prefix (max 5 characters)—ULIDs are 26 chars, plus 5-char prefix and underscore = 32 chars max
15
15
4. Follow the naming convention `[Entity]Id`
16
16
5. Include the `[JsonConverter]` attribute for proper serialization
17
17
6. Always override `ToString()` in the concrete class—record types don't inherit this from the base class
0 commit comments