Search code examples
c#.netsqlitesqlite-netsqlite-net-pcl

How to use Immutable Objects with SQLite?


I keep getting the following error when trying to initialize my SQLite-NET database:

Cannot create a table without columns (does 'PersonModel' have public properties?)

I have a class PersonModel that I want to be immutable, however SQLite is telling me that PersonModel must be mutable, e.g. each property must use public set;.

How can I continue using SQLite-NET with immutable properties?

class Person
{
    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public string FirstName { get; } //Read-only Property, cannot be changed after initialization
    public string LastName { get; } //Read-only Property, cannot be changed after initialization
}

Solution

  • Explanation

    That error is happening because SQLite-NET uses Reflection to initialize the objects it retrieves from our database, and Reflection requires public set; to initialize each property.

    Answer

    We can take advantage of Init-Only Setters, new in C# 9.0.

    Init-Only Setters allow us to define properties that can be set during initialization, AND cannot be changed. In other words init-only setters let us create immutable objects, AND they allow Reflection to create Immutable Objects!

    I go deeper into this topic in this blog post: https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite-net/

    Code

    Remove the constructor on Person (Reflection requires a parameterless constructor), and implement init-only setters for each property:

    class Person
    {
        public string FirstName { get; init; } //Read-only Property, can be set during initialization, but cannot be changed after initialization
        public string LastName { get; init; } //Read-only Property, can be set during initialization, but cannot be changed after initialization
    }