--- title: "Type Converters" description: "Convert between C# types and database types with custom converters." canonical: "https://roomsharp.dev/docs/v0.5.3/type-converters" source: "src/content/v0.5.3/type-converters.mdx" --- # Type Converters Type converters allow you to map complex C# types to database-compatible types and vice versa. ## Creating a Type Converter Implement `ITypeConverter` or derive from `TypeConverter`: ```csharp public class DateTimeTicksConverter : TypeConverter { public override DateTime FromProvider(long provider) => new(provider, DateTimeKind.Utc); public override long ToProvider(DateTime model) => model.ToUniversalTime().Ticks; } ``` ## Applying Type Converters Annotate entity properties with `[TypeConverter(ConverterType = typeof(...))]`: ```csharp [Entity(TableName = "posts")] public class Post { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } [TypeConverter(ConverterType = typeof(DateTimeTicksConverter))] public DateTime PublishedAt { get; set; } } ``` ## Generic Type Converter Attribute For simpler syntax, use the generic attribute (C# 11+): ```csharp [Entity(TableName = "users")] public class User { [PrimaryKey(AutoGenerate = true)] public long Id { get; set; } [TypeConverter>] public UserStatus Status { get; set; } [TypeConverter>] public UserSettings? Settings { get; set; } } ``` ## Common Converters ### Enum to String ```csharp public class EnumToStringConverter : TypeConverter where TEnum : struct, Enum { public override TEnum FromProvider(string provider) => Enum.Parse(provider); public override string ToProvider(TEnum model) => model.ToString(); } ``` ### JSON Serialization ```csharp public class JsonConverter : TypeConverter { public override T FromProvider(string provider) => JsonSerializer.Deserialize(provider)!; public override string ToProvider(T model) => JsonSerializer.Serialize(model); } ``` ### DateTime to Ticks ```csharp public class DateTimeTicksConverter : TypeConverter { public override DateTime FromProvider(long provider) => new(provider, DateTimeKind.Utc); public override long ToProvider(DateTime model) => model.ToUniversalTime().Ticks; } ``` ### Guid to String ```csharp public class GuidStringConverter : TypeConverter { public override Guid FromProvider(string provider) => Guid.Parse(provider); public override string ToProvider(Guid model) => model.ToString("D"); } ``` ## Registering Converters at Runtime RoomSharp discovers converters on entities automatically, but you can also register them at runtime: ```csharp var db = RoomDatabase.Builder() .UseSqlite("app.db") .Build(); // Register custom converter db.Converters.Register(new MyCustomConverter()); ``` Converters discovered on entities are automatically registered. Use runtime registration for converters that apply to multiple entities or when you need dynamic behavior. ## Nullable Type Handling For nullable types, handle null values appropriately: ```csharp public class NullableDateTimeTicksConverter : TypeConverter { public override DateTime? FromProvider(long? provider) => provider.HasValue ? new DateTime(provider.Value, DateTimeKind.Utc) : null; public override long? ToProvider(DateTime? model) => model?.ToUniversalTime().Ticks; } ``` ## Type Mapping Reference Default type mappings without converters: | C# Type | SQLite Type | Notes | |---------|-------------|-------| | `int`, `long`, `short` | INTEGER | Numeric types | | `string` | TEXT | Text data | | `double`, `float`, `decimal` | REAL | Floating point | | `byte[]` | BLOB | Binary data | | `DateTime` | INTEGER | Stored as Unix ticks | | `bool` | INTEGER | 0 or 1 | | `Guid` | TEXT | String representation | Use type converters when you need different storage formats or want to serialize complex objects to JSON/string.