Reading objects from the database

While schema-less databases make it extremely easy to write documents of different forms to the same collection, this can pose problems when reading documents back from that same collection and deserializing them. In reality, the problem of schema management is not removed, but deferred to a later point in time.

Continuing the example from the previous section, deserializing the first person that was saved on the new C# Person class definition will result in a null value for the city property. This can be unexpected, since the C# code guarantees that a person without a city can never be constructed. This is a clear example of the challenges that schema-less databases pose.

In this example, the issue can be circumvented by updating the Person class to the following:

public class Person
{
[JsonConstructor]
private Person() {}

public Person(string name, string city) {
Name = name ?? throw new ArgumentNullException();
City = city ?? throw new ArgumentNullException();
}

[JsonProperty]
public string Name { get; private set; }

[JsonIgnore]
private string _city;

[JsonProperty]
public string City {
get { return _city; }
private set { _city = value ?? _city = string.Empty}
}
}

Next to this scenario, where a property was added, there are many other scenarios that will require the C# class to be adapted in order to handle deserialization scenarios. Some examples are as follows:

  • Adding a property of a primitive type
  • Adding a complex property, another object, or an array
  • Renaming a property
  • Replacing a property of a primitive type with a complex property
  • Making nullable properties non-nullable

Adding code to objects to handle these situations increases the size and complexity of the code base, and pollutes the primary code base with the capabilities for coping with past situations. Especially when this happens often, this can lead to unwanted complications in a code base. To prevent this, a possible solution is to go through the following process whenever the schema of an object changes:

  1. Change the schema of the object, ensuring that there are only properties added. Even when the goal is to remove a property, at this stage, only a property with the new name is added.
  2. Implement logic on the object to cope with the deserialization of old versions of the object.
  3. Deploy the new version of the object.
  4. Start a background process that loads all objects of the type from the database one by one, and saves them back to the database.
  5. Once the background process has processed all existing entities, remove the code that is responsible for coping with the schema change during deserialization from the code base, along with any properties that are no longer used.

Using this approach, all changes are propagated to all stored versions of the object over a period of time. The downside to this approach is that the change to the object's structure is spread over two changes that must be deployed separately. Also, deployment of the second change must wait until all objects in the database have been converted.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.200.136