---
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 |