> ## Content Index
> Fetch the complete content index at: https://codetraveler.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# Using Immutable Objects with SQLite-Net
- URL: https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite-net/
- Published: 2020-11-11T20:39:11.000Z
- Updated: 2020-11-11T20:58:59.000Z
- Description: SQLite-NET has become the most popular database, especially amongst Xamarin developers, but it hasn't supported Immutable Objects, until now! Thanks to Init-Only Properties in C#9.0, we can now use Immutable Objects with our SQLite database!
- Author: Brandon Minnick
- Tags: Xamarin, SQLite, SQLite-net, .NET, .NET 5, init, C#9.0, C#

[SQLite-NET](https://www.nuget.org/packages/sqlite-net-pcl/?ref=codetraveler.io) has become the most popular database, especially amongst [Xamarin](https://dotnet.microsoft.com/learn/xamarin/what-is-xamarin?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io) developers, but it hasn't supported Immutable Objects, until now!

If you're already familiar with Immutable vs. Mutable objects, feel free to scroll straight to **Immutable Objects + SQLite-net**.

## What is an Immutable Object?

An [Immutable Object](https://devblogs.microsoft.com/premier-developer/simple-immutable-objects/?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io) is a object whose values are defined at initialization and cannot be changed. Let's take a look at the example, below.

### Immutable Object

```csharp
public 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
}
```

This is an immutable object whose values are required at initialization and can never be changed.

```charp
var brandon = new Person("Brandon", "Minnick");

// The values of `brandon` can never be changed 
// I.e. `person.FirstName = "Kim"` generates a compiler error
```

## Why Immutable Objects?

Now, you're probably wondering "Who cares about immutability?" 

Immutability is super helpful for using [DTOs (Data Transfer Objects)](https://docs.microsoft.com/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io), e.g. objects retrieved from an API or a Database. 

A pure DTO should always represent the transferred data, i.e. we should never modify a DTO.

## Immutable Objects + SQLite-NET

SQLite always required mutable objects (i.e. every property had to have a `public get` and a `public set`) because SQLite uses [Reflection](https://docs.microsoft.com/dotnet/framework/reflection-and-codedom/reflection?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io) to create the objects it retrieves from our database.

But recently, Microsoft released [C# 9.0](https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io) which introduced [Init-Only Setters](https://docs.microsoft.com/dotnet/csharp/language-reference/proposals/csharp-9.0/init?WT.mc%5Fid=mobile-10939-bramin&ref=codetraveler.io)! 

This allows 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 EVEN BETTER, they **allow Reflection to create Immutable Objects**! 🎉

### Immutable Object using Init-Only Setters

```csharp
public 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
}
```

This allows properties to be set during initialization AND does not allow the properties to be changed.

```csharp
var brandon = new Person
{
    FirstName = "Brandon",
    LastName = "Minnick"
};

// The values of `brandon` can never be changed 
// I.e. `person.FirstName = "Kim"` now causes a compiler error
```

And the best part is that it is ALSO valid for SQLite because Reflection can still set the properties during initialization!!! 

## Example

If you're looking for a completed sample, check out this code from [InvestmentDataSampleApp](https://github.com/brminnick/InvestmentDataSampleApp/blob/main/Src/InvestmentDataSampleApp/Models/OpportunityModel.cs?ref=codetraveler.io). 

```csharp
using SQLite;

static class Program
{
    public static async Task Main()
    {
    	var databasePath = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "Database.db3");
        var databaseConnection = new SQLiteAsyncConnection(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
        await databaseConnection.CreateTablesAsync(CreateFlags.None, typeof(PersonModel));
            
        // Save Immutable Object to Database
        await databaseConnection.InsertOrReplaceAsync(new Person
        {
            FirstName = "Brandon",
            LastName = "Minnick"
        });
            
        // Save Immutable Object to Database
        await databaseConnection.InsertOrReplaceAsync(new Person
        {
            FirstName = "James",
            LastName = "Montemagno"
        });
            
        //Retrieve all immutable obects from Database, placing it into a read-only List (e.g. an immutable List)
        IReadonlyList<PersonModel> allPeople = await databaseConnection.Table<PersonModel>().ToListAsync();        
    }
}

class PersonModel
{
    [PrimaryKey, AutoIncrement] //PrimaryKey must be nullable: https://github.com/praeclarum/sqlite-net/issues/327
    public int? ID { get; init;}
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
```