--- title: "Attributes Reference" description: "Comprehensive guide to all RoomSharp attributes" canonical: "https://roomsharp.dev/docs/v0.5.4/attributes" source: "src/content/v0.5.4/attributes.mdx" --- # Attributes Reference This page provides a complete reference for all attributes in RoomSharp. ## Attribute Coverage | Area | Attributes | |------|------------| | Entity mapping | `[Entity]`, `[PrimaryKey]`, `[ColumnInfo]`, `[Unique]`, `[Index]`, `[Ignore]`, `[ForeignKey]`, `[Embedded]`, `[DatabaseView]` | | DAO operations | `[Dao]`, `[Query]`, `[Insert]`, `[Update]`, `[Delete]`, `[Upsert]`, `[BulkInsert]`, `[Transaction]` | | Lifecycle | `[SoftDelete]`, `[Encrypted]`, `[Auditable]` | | Relations | `[Relation]`, `[Junction]` | | Database setup | `[Database]`, `[TypeConverter]`, `[RequiresAsyncInitialization]`, `[AllowDoubleCheckedLock]` | | Migrations | `[AutoMigration]`, `[RenameTable]`, `[DeleteTable]`, `[AddColumn]`, `[DeleteColumn]`, `[ColumnRename]` | | Advanced | `[Seeder]`, `[Fts]`, `[MapInfo]` | --- ## Entity Mapping Attributes ### `[Entity]` Marks a class as a database entity (table). ```csharp [Entity(TableName = "users")] public class User { ... } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `TableName` | `string` | Database table name (defaults to class name) | | `Indices` | `string[]?` | Simple index column list | | `PrimaryKeys` | `string[]?` | Composite primary key column/property names | --- ### `[PrimaryKey]` Marks a property as the primary key. ```csharp [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } ``` **Properties:** | Property | Type | Default | Description | |----------|------|---------|-------------| | `AutoGenerate` | `bool` | `false` | Auto-increment the key value | --- ### `[ColumnInfo]` Customizes column mapping and type affinity. ```csharp [ColumnInfo(Name = "user_email", TypeAffinity = "TEXT")] public string Email { get; set; } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Name` | `string?` | Database column name | | `TypeAffinity` | `string?` | Provider type affinity or SQL type hint | | `DefaultValue` | `string?` | Default SQL value used in generated schema | | `Collate` | `string?` | Collation name | --- ### `[Unique]` Marks a property as having a unique constraint. ```csharp [Unique] public required string Email { get; set; } ``` For composite unique constraints, use the `[Index]` attribute with `Unique = true`. --- ### `[Index]` Defines an index on the entity. ```csharp [Entity(TableName = "users")] [Index(Value = ["Email"], Unique = true)] [Index(Value = ["LastName", "FirstName"])] public class User { ... } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Value` | `string[]` | Column names to include in the index | | `Unique` | `bool` | Whether the index enforces uniqueness | --- ### `[Ignore]` Excludes a property from database mapping. ```csharp [Ignore] public string TempData { get; set; } ``` --- ### `[ForeignKey]` Defines a foreign key constraint. ```csharp [ForeignKey(Entity = typeof(User), OnDelete = ForeignKeyAction.Cascade)] public long UserId { get; set; } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Entity` | `Type` | Referenced entity type | | `ParentColumns` | `string[]?` | Referenced parent columns | | `ChildColumns` | `string[]?` | Local child columns | | `OnDelete` | `ForeignKeyAction` | Action on delete (Cascade, Restrict, SetNull, NoAction) | | `OnUpdate` | `ForeignKeyAction` | Action on update | | `Deferred` | `bool` | Defers constraint checking when supported by provider | --- ### `[Embedded]` Embeds another object's properties as columns in the parent entity. ```csharp [Entity(TableName = "orders")] public class Order { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } [Embedded(Prefix = "billing_")] public Address BillingAddress { get; set; } [Embedded(Prefix = "shipping_")] public Address ShippingAddress { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string PostalCode { get; set; } } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Prefix` | `string?` | Column name prefix (e.g., `billing_street`, `billing_city`) | Embedded objects are flattened into the parent table. Use `Prefix` to disambiguate multiple embedded objects of the same type. **Usage in DTO Projections:** ```csharp public class UserWithPosts { [Embedded] public User User { get; set; } = default!; public long Id => User.Id; [Relation(Entity = typeof(Post), ParentColumn = "Id", EntityColumn = "UserId")] public List Posts { get; set; } = new(); } ``` --- ### `[DatabaseView]` Defines a read-only database view projection. ```csharp [DatabaseView( ViewName = "active_users", Query = "SELECT Id, Email, Name FROM users WHERE IsActive = 1", Managed = true)] public class ActiveUser { public long Id { get; set; } public string Email { get; set; } public string Name { get; set; } } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `ViewName` | `string?` | View name in the database | | `Query` | `string?` | SQL query that defines the view shape | | `Managed` | `bool` | Enables compile-time validation, schema export, and schema validation for the view definition | Views are read-only. You cannot use `[Insert]`, `[Update]`, or `[Delete]` on view entities. When `Managed = true`, RoomSharp reports diagnostics if `Query` is missing, is not a `SELECT`, uses `SELECT *`, or does not select a mapped projection property. Schema export also includes managed views, and schema validation checks that the live database contains the expected view definition. RoomSharp does not automatically execute `CREATE VIEW`; create the view in a migration. --- ## DAO Operation Attributes ### `[Dao]` Marks an interface as a Data Access Object. ```csharp [Dao] public interface IUserDao { ... } ``` --- ### `[Query]` Defines a SQL query method. ```csharp [Query("SELECT * FROM users WHERE Id = :id")] Task GetById(long id); [Query("SELECT * FROM users WHERE Email LIKE :pattern")] Task> SearchByEmail(string pattern); [Query("SELECT COUNT(*) FROM users")] Task GetCount(); ``` Use `:paramName` for named parameters. They map to method parameter names. **Properties:** | Property | Type | Default | Description | |----------|------|---------|-------------| | `Value` | `string` | required | SQL query text | | `NoTracking` | `bool` | `false` | Disable change tracking/mapper caching for large or read-only query paths | --- ### `[Insert]` Defines an insert method with optional conflict resolution. ```csharp [Insert] long Insert(User user); [Insert] long InsertAll(params User[] users); [Insert(OnConflict = OnConflictStrategy.Replace)] long Upsert(User user); ``` **Properties:** | Property | Type | Default | Description | |----------|------|---------|-------------| | `OnConflict` | `OnConflictStrategy` | `Abort` | Conflict resolution strategy | #### `OnConflictStrategy` Enum | Value | Description | |-------|-------------| | `Abort` | Abort the operation and rollback (default) | | `Replace` | Replace the existing row with the new values | | `Ignore` | Silently ignore the conflict, keep existing row | | `Fail` | Fail immediately without rollback | | `Rollback` | Rollback to the last commit point | **Example with Replace:** ```csharp [Insert(OnConflict = OnConflictStrategy.Replace)] long UpsertUser(User user); // Creates a new user or replaces existing one based on primary key db.UserDao.UpsertUser(new User { Id = 1, Email = "new@email.com", Name = "Updated" }); ``` --- ### `[Upsert]` Defines an upsert (insert or update) method. ```csharp [Upsert] long Upsert(User user); [Upsert] Task UpsertAsync(User user); ``` `[Upsert]` is equivalent to `[Insert(OnConflict = OnConflictStrategy.Replace)]` but more explicit. --- ### `[BulkInsert]` Defines a high-performance bulk insert method. ```csharp [BulkInsert] long InsertBulk(IEnumerable users); [BulkInsert(BatchSize = 5000)] long InsertLargeBatch(IEnumerable users); [BulkInsert] Task InsertBulkAsync(IAsyncEnumerable users); ``` **Properties:** | Property | Type | Default | Description | |----------|------|---------|-------------| | `BatchSize` | `int` | `1000` | Number of rows per batch | `BulkInsert` is optimized for large datasets. Use `IAsyncEnumerable` for streaming data without loading everything into memory. **Provider-Specific Optimizations:** | Provider | Method | Notes | |----------|--------|-------| | SQLite | Multi-value INSERT | Batched single statements | | PostgreSQL | COPY / unnest | Uses COPY or unnest for bulk loading | | MySQL | Multi-value INSERT | Batched single statements | | SQL Server | SqlBulkCopy | Native bulk copy API | --- ### `[Update]` Defines an update method. ```csharp [Update] int Update(User user); [Update] Task UpdateAsync(User user); ``` --- ### `[Delete]` Defines a delete method. ```csharp [Delete] int Delete(User user); [Delete] Task DeleteAsync(User user); ``` --- ### `[Transaction]` Wraps a method in a database transaction. ```csharp [Transaction] public async Task TransferAsync(long fromId, long toId, decimal amount) { var from = await GetByIdAsync(fromId); var to = await GetByIdAsync(toId); from.Balance -= amount; to.Balance += amount; await UpdateAsync(from); await UpdateAsync(to); } ``` `[Transaction]` is applied to interface methods with bodies (default interface methods). The source generator wraps the emitted body in the appropriate transaction helper. `[Transaction]` is not supported on `IAsyncEnumerable` streaming methods. Streaming requires an explicit caller-owned transaction/session lifetime. --- ## Smart Lifecycle Attributes ### `[SoftDelete]` Marks an entity so generated delete operations update a marker column instead of physically removing the row. ```csharp [SoftDelete(SoftDeleteType.DateTime, Column = "deleted_at")] [Entity(TableName = "customers")] public sealed class Customer { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } public DateTime? DeletedAt { get; set; } } ``` | Property | Type | Default | Description | |----------|------|---------|-------------| | `Type` | `SoftDeleteType` | `DateTime` | `DateTime` marker or `Bool` marker | | `Column` | `string?` | `deleted_at` / `is_deleted` | Marker column name | Generated DAOs can expose restore and hard-delete methods for soft-delete entities, and SELECT queries are automatically filtered by default. ### `[Encrypted]` Marks a property for transparent encryption/decryption. ```csharp [Encrypted] public string? NationalId { get; set; } [Encrypted(Algorithm = "aes-gcm")] public string? PrivateNote { get; set; } ``` | Property | Type | Default | Description | |----------|------|---------|-------------| | `Algorithm` | `string?` | provider default | Optional algorithm hint passed to the configured encryption provider | Encrypted properties require an `IEncryptionProvider` to be registered in the database builder or through `RoomSharp.DependencyInjection`. ### `[Auditable]` Marks an entity for automatic audit column population on insert/update. ```csharp [Auditable(TrackCreatedBy = true)] public sealed class Invoice { public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } public string? CreatedBy { get; set; } } ``` | Property | Type | Default | Description | |----------|------|---------|-------------| | `CreatedAtColumn` | `string` | `created_at` | Creation timestamp column | | `UpdatedAtColumn` | `string` | `updated_at` | Last update timestamp column | | `TrackCreatedBy` | `bool` | `false` | Populate creator column through `IAuditContext` | | `CreatedByColumn` | `string` | `created_by` | Creator column name | --- ## Database Configuration Attributes ### `[Database]` Marks a class as the database entry point. ```csharp [Database(Version = 1, Entities = [typeof(User), typeof(Order)])] public abstract class AppDatabase : RoomDatabase { public abstract IUserDao UserDao { get; } public abstract IOrderDao OrderDao { get; } } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Version` | `int` | Database schema version (for migrations) | | `Entities` | `Type[]` | Entity types included in this database | | `Views` | `Type[]?` | Database view types included in this database | | `ExportSchema` | `bool` | Export schema metadata when enabled | | `EnableForeignKeys` | `bool` | Enable foreign key enforcement where supported | | `DaoInstanceType` | `InstanceType` | DAO creation strategy | | `ConcurrencyMode` | `ConcurrencyMode` | `Serialized` (default) or `Parallel` | ### DAO Instance Types | Value | Description | |-------|-------------| | `Default` | Thread-safe lazy DAO initialization | | `Eager` | Create DAO instances in the database constructor | | `Transient` | Create a new DAO instance on each property access | | `AsyncLazy` | Async initialization path for advanced scenarios | | `DoubleCheckedLock` | Advanced lazy mode for highly tuned applications | ### `[RequiresAsyncInitialization]` Marks a database/DAO-related type that needs the async initialization path. ```csharp [RequiresAsyncInitialization] public sealed class ReportingDatabase : RoomDatabase { } ``` ### `[AllowDoubleCheckedLock]` Explicitly allows double-checked locking for advanced generated initialization paths. ```csharp [AllowDoubleCheckedLock] public sealed class HotPathDatabase : RoomDatabase { } ``` --- ### `[TypeConverter]` Registers a custom type converter at the database level. ```csharp [Database(Version = 1, Entities = [typeof(Post)])] [TypeConverter(typeof(DateTimeTicksConverter))] public abstract class AppDatabase : RoomDatabase { ... } ``` **Property-level usage:** ```csharp [Entity(TableName = "posts")] public class Post { [TypeConverter(ConverterType = typeof(DateTimeTicksConverter))] public DateTime PublishedAt { get; set; } [TypeConverter(ConverterType = typeof(JsonConverter>))] public List Tags { get; set; } } ``` --- ## Relation Attributes ### `[Relation]` Defines a relationship to load related entities. ```csharp public class UserWithPosts { [Embedded] public User User { get; set; } = default!; [Relation(Entity = typeof(Post), ParentColumn = "Id", EntityColumn = "UserId")] public List Posts { get; set; } = new(); } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `Entity` | `Type` | Related entity type | | `ParentColumn` | `string` | Column in the parent entity | | `EntityColumn` | `string` | Column in the related entity | | `AssociateBy` | `string?` | Simple junction table name for many-to-many relations | ### `[Junction]` Provides explicit many-to-many junction metadata. ```csharp public sealed class StudentWithCourses { [Relation(Entity = typeof(Course), ParentColumn = "Id", EntityColumn = "Id")] [Junction(Value = typeof(StudentCourse), ParentColumn = "StudentId", EntityColumn = "CourseId")] public List Courses { get; set; } = []; } ``` | Property | Type | Description | |----------|------|-------------| | `Value` | `Type?` | Junction entity type | | `ParentColumn` | `string?` | Junction column pointing to the parent | | `EntityColumn` | `string?` | Junction column pointing to the related entity | --- ## Seeding Attributes ### `[Seeder]` Marks a class as a database seeder with configuration options. ```csharp [Seeder( EntityType = typeof(User), Order = 10, DependsOn = [typeof(RoleSeeder)], Environments = ["Development", "Staging"] )] public sealed class UserSeeder : IRoomSeeder { public string? SeedVersion => "1.0.0"; public async ValueTask SeedAsync(SeederContext ctx) { var dao = ((AppDatabase)ctx.Database).UserDao; if (!await dao.ExistsByEmailAsync("admin@local")) { await dao.InsertAsync(new User { Email = "admin@local", Role = "Admin" }); } ctx.LogMessage("UserSeeder completed"); } } ``` **Properties:** | Property | Type | Default | Description | |----------|------|---------|-------------| | `EntityType` | `Type?` | `null` | Entity type this seeder populates (documentation) | | `Name` | `string?` | `null` | Override seeder name (defaults to class name) | | `Order` | `int` | `0` | Execution order within same dependency level (lower runs first) | | `DependsOn` | `Type[]?` | `null` | Seeder types that must run before this one | | `Environments` | `string[]?` | `null` | Allowed environments (empty = all) | | `RunInTransaction` | `bool` | `true` | Wrap seeding in a transaction | | `Repeatable` | `bool` | `false` | Can re-run based on `SeedVersion` hash | Use `SeedVersion` property in your seeder class to trigger re-runs. When the version changes, the seeder will run again even if it was previously applied. --- ## Migration Attributes ### `[AutoMigration]` Defines an automatic migration between schema versions. ```csharp [Database(Version = 3, Entities = [typeof(User)])] [AutoMigration(From = 1, To = 2, Spec = typeof(UserTableSpec))] [AutoMigration(From = 2, To = 3)] public abstract class AppDatabase : RoomDatabase { ... } ``` **Properties:** | Property | Type | Description | |----------|------|-------------| | `From` | `int` | Starting schema version | | `To` | `int` | Target schema version | | `Spec` | `Type?` | Optional `IAutoMigrationSpec` implementation | --- ### Migration Spec Attributes Use these on `IAutoMigrationSpec` implementations: ```csharp [RenameTable(FromTableName = "old_users", ToTableName = "users")] [DeleteColumn(TableName = "users", ColumnName = "legacy_flag")] public sealed class UserTableSpec : IAutoMigrationSpec { [ColumnRename(TableName = "users", FromColumnName = "full_name", ToColumnName = "name")] public string UsersTable => "users"; } ``` | Attribute | Description | |-----------|-------------| | `[RenameTable]` | Rename a table | | `[DeleteTable]` | Delete a table | | `[AddColumn]` | Add a new column | | `[DeleteColumn]` | Delete a column | | `[ColumnRename]` | Rename a column | ### `[AddColumn]` Type-Safe Properties `[AddColumn]` can use either raw `ColumnDefinition` or provider-aware type metadata. | Property | Type | Description | |----------|------|-------------| | `TableName` | `string?` | Target table | | `ColumnName` | `string?` | New column name | | `ColumnDefinition` | `string?` | Provider-specific raw SQL definition | | `ColumnType` | `Type?` | CLR type used to infer provider SQL type | | `Nullable` | `bool` | Whether the column allows NULL | | `DefaultValue` | `object?` | Default value | | `MaxLength` | `int` | Max length for string columns | --- ## Advanced Attributes ### `[Fts]` Declares full-text-search metadata for an entity. ```csharp [Fts(Provider = FtsProviderKind.SQLite, Tokenizer = "unicode61")] public sealed class DocumentSearch { } ``` | Property | Type | Default | Description | |----------|------|---------|-------------| | `Provider` | `FtsProviderKind` | `SQLite` | FTS provider dialect | | `Version` | `int` | `4` | SQLite FTS version metadata | | `Tokenizer` | `string` | `simple` | Tokenizer hint | | `ContentEntity` | `string[]?` | `null` | External content metadata | | `LanguageId` | `string?` | `null` | Provider language identifier | ### `[MapInfo]` Provides multi-map key/value metadata for advanced generated mapping scenarios. ```csharp [MapInfo(KeyColumn = "UserId", ValueColumn = "RoleId")] Task> GetUserRolesAsync(); ``` | Property | Type | Description | |----------|------|-------------| | `KeyColumn` | `string?` | Key column name | | `KeyTable` | `string?` | Key table name | | `ValueColumn` | `string?` | Value column name | | `ValueTable` | `string?` | Value table name |