Immutable Models in MVVM

10-22-04 025
Source: flickr/ Jeff Attaway


The first M stands for Model – an implementation of the application’s domain model that includes a data model along with business and validation logic. Examples of model objects include repositories, business objects, data transfer objects (DTOs), Plain Old CLR Objects (POCOs), and generated entity and proxy objects.

definition source


In object-oriented and functional programming, an immutable object(unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.

definition source

Why bother?

Imagine the next simple situation, your application downloads a JSON,  deserialises it to an object and then presents the downloaded data. You would expect the downloaded data to be one-to-one to the data on the remote server, however the data can be accidentally or intentionally mutated.

Here is an example of a mutable Model:

public class MyMutableObject
    public long Id { get; set; }
    public string Title { get; set; }
    public List<string> Contents { get; set; }

All the properties has public setters which means that any of those can be changed after the object creation. Even if we make all the setters private, it could be still possible to manipulate data within the List.

Here is an example of immutable Model:

public sealed class MyImmutableObject
    public long Id { get; }
    public string Title { get; }
    public IReadOnlyCollection<string> Contents { get; }

    public MyImmutableObject(
        long id,
        string title,
        IReadOnlyCollection<string> contents)
        Id = id;
        Title = title;
        Contents = contents;

There are no public setters available and mutable collection type is replaced by “immutable” one. There is no option to extend this class as well as changing the data after the object is created.

IReadOnlyCollection is not a real immutable collection but an immutable facade. It is not thread safe and possible to cast to IList and try to manipulate the collection, however System.NotSupportedException will be thrown.

Alternatively we can add a System.Collections.Immutable NuGet package and replace IReadOnlyCollection<T> by IImmutableList<T> if we want a real immutable collection.

JSON Deserialization

Often Models used for deserialization and it can be tricky to deserialize JSON to immutable object. Luckily with Json.NET it is not an issue. We can easily serialize and deserialize MyImmutableObject:

var myImmutableObject = new MyImmutableObject(
        id: 1,
        title: “Test”,
        contents: new List<string> { “One”, “Two”, “Three” });
var json = JsonConvert.SerializeObject(myImmutableObject);
var deserializedObject = JsonConvert.DeserializeObject<MyImmutableObject>(json);

Please note that if your Model has more than one constructor you will need to mark  one for deserialization explicitly,  by adding a JsonConstructor attribute.


With .NET Standard we can use EntityFramework Core in our Xamarin.Forms applications which is great! And it is great twice since we can have a code first  immutable model fully supported by EF.


public sealed class ToDoModel
    public int Id { get; private set; }
    public string Title { get; private set; }
    public string Notes { get; private set; }
    public DateTimeOffset CreatedAt { get; private set; }
    public DateTimeOffset? UpdatedAt { get; private set; }

    ToDoModel() { /* EF requires a parameterless constructor. */ }

    public ToDoModel(
        int id,
        string title,
        string notes,
        DateTimeOffset createdAt,
        DateTimeOffset? updatedAt)
        Id = id;
        Title = title;
        Notes = notes;
        CreatedAt = createdAt;
        UpdatedAt = updatedAt;

When using an “immutable” Model with EF keep in mind:

  • Parameterless constructor – is required, should be private.
  • Setters – are required, should private.
  • Object tracking – should be disabled.


  • SQLite.NET did not work properly with private constructor and setters.
  • We have to count with private setters since it is still possible to change a value with a private setter within the same class.


In this blogpost we discussed how to make immutable Models and checked few common scenarios. I would recommend to start immutable and change to mutable if necessary. Here are few recommendations to keep in mind:

  • Forget about private setters: prop -> propg
  • Make publicly available properties readonly
  • Use constructors
  • Seal classes
  • Use immutable collections or at least IReadOnlyCollection<T>
  • The goal is not to get 100% immutability but to improve code quality

Immutability is a very interesting topic which has pros and cons. For example it may harm performance or introduce unnecessary complexity in some cases, so use it wisely. There are few great resources that I would recommend to get familiar with:



Entity Framework DB First and Computed Columns

Imagine you have a lovely DB first approach in place. There is a table “Fruits” with a column “WikiLink”. This column is getting populated on insert, using a trigger on the DB level. Can you spot “the” problem here?

Let’s try to understand how EF returns the DB generated entity Id from the DB right after the insert. The code below demonstrates a standard way to insert a new entity with EF:

var fruit = new Fruit { Family = “Rosaceae”, Name = “Apple” };
await dbContext.SaveChangesAsync();
// fruit.Id is auto-generated on the DB level and accessible after insert
// fruid.WikiLink is null

The Id column marked as identity, therefor it is recognised as a value generated on DB level. If you will use a DB profiler you will actually see:

— T-SQL Pseudocode for -> dbContext.Fruits.Add(fruit);
INSERT INTO [dbo].[Fruits] (Family, Name)
VALUES (“Rosaceae”, “Apple”)

It is insert and select in one query. Now back to our problem with ‘WikiLink’. What we would like to achieve is:

INSERT INTO [dbo].[Fruits] (Family, Name)
VALUES (“Rosaceae”, “Apple”)

When you use a code first approach, you have an option of explicitly marking an entity’s property as db generated with an attribute:

public string WikiLink { get; set; }

However, with DB first approach you don’t have that option, and since there is a trigger behind this column, there is no way for EF to understand that it is generated on the DB level.

Unfortunately, it is not easily solvable with DB first approach. There are a couple of workarounds we could think about:

  1. We can try to manipulate “manually” the auto-generated edmx file and set the “WikiLink” to db computed. Which is a bad idea, because this change will get lost with the next model update as it is being regenerated on each change.
  2. Another option will be to query the DB right after the insert, to get the full row data:

var fruit = new Fruit { Family = “Rosaceae”, Name = “Apple” };
await dbContext.SaveChangesAsync();
await dbContext.Entry(fruit).ReloadAsync()
// fruid.WikiLink is not null anymore

The disadvantage is obvious – additional db query:

— T-SQL Pseudocode for -> dbContext.Fruits.Add(fruit);
INSERT INTO [dbo].[Fruits] (Family, Name)
VALUES (“Rosaceae”, “Apple”)

— T-SQL Pseudocode for -> await dbContext.Entry(fruit).ReloadAsync()
SELECT FROM * [dbo].[Fruits]
WHERE Id = 99;

However, it could be good enough for some projects.

If you can modify the DB scheme, the solution is quite simple – replace the trigger by a computed column:

— T-SQL Pseudocode for
alter table [dbo].[Fruits]
add [WikiLink] as concat(N’_ttp://’, Id )

This way you may gain more performance. Since you may have a ‘RowVersion’ column which will be calculated twice because of the trigger. Not to mention that the DB structure is much more readable, compare to unnecessary trigger.

There might be another workarounds for this issue if you don’t have access or you can’t modify the DB. I would like to hear about your experience, so please share via comments.

Entity Framework Database First Generalising Timestamps

Using Entity Framework is extremely easy and straight forward unless you have a large amount of entities and business rules to apply. You are lucky if you have a code first approach, however some times database first approach is in place and there are some limitations. For example, as the DbContext is autogenerated using T4, it is hard to introduce general behaviours, like updating CreatedAt, UpdatedAt and DeletedAt properties globally upon saving.

There could be different solutions for the problem I mentioned earlier, however there is a simple one that may work as well. Since all auto-generated files by EntityFramework marked as partial, we could easily extend them. Lets start!

Continue reading “Entity Framework Database First Generalising Timestamps”