Navigation

Realm Objects

Overview

MongoDB Realm applications model data as objects composed of field-value pairs that each contain one or more primitive data types or other Realm objects. Realm objects are essentially the same as regular objects, but they also include additional features like real-time updating data views and reactive change event handlers.

Every Realm object has an object type that refers to the object’s class. Objects of the same type share an object schema that defines the properties and relationships of those objects. In most languages you define object schemas using the native class implementation.

Example

The following code block shows an object schema that describes a Dog. Every Dog object must include a Name and may optionally include the dog’s Age, Breed and a list of people that represents the dog’s Owners.

public class Dog : RealmObject
{
    [Required]
    public string Name { get; set; }

    public int Age { get; set; }
    public string Breed { get; set; }
    public IList<Person> Owners { get; }
}

public class Person : RealmObject
{
    [Required]
    public string Name { get; set; }
    //etc...
}
/*  To add items to the IList<T>:
 
    var dog = new Dog();
    var caleb = new Person { Name = "Caleb" };
    dog.Owners.Add(caleb);
    
 */

Note

To define a collection of objects within an object, use an IList<T> with only a getter. You do not need to initialize it in the constructor, as realm will generate a collection instance the first time the property is accessed.

Key Concepts

Live Object

Objects in Realm clients are live objects that update automatically to reflect data changes, including synced remote changes, and emit notification events that you can subscribe to whenever their underlying data changes. You can use live objects to work with object-oriented data natively without an ORM tool.

Live objects are direct proxies to the underlying stored data, which means that a live object doesn’t directly contain data. Instead, a live object always references the most up-to-date data on disk and lazy loads property values when you access them from a collection. This means that a realm can contain many objects but only pay the performance cost for data that the application is actually using.

Valid write operations on a live object automatically persist to the realm and propagate to any other synced clients. You do not need to call an update method, modify the realm, or otherwise “push” updates.

Object Schema

An object schema is a configuration object that defines the fields and relationships of a Realm object type. Realm client applications define object schemas with the native class implementation in their respective language using the Realm Object Model.

Object schemas specify constraints on object properties such as the data type of each property and whether or not a property is required. Schemas can also define relationships between object types in a realm.

Every Realm app has a Realm Schema composed of a list of object schemas for each type of object that the realms in that application may contain. MongoDB Realm guarantees that all objects in a realm conform to the schema for their object type and validates objects whenever they’re created, modified, or deleted.

Primary Key

A primary key is a property that uniquely identifies an object. You may define a primary key on a single property for an object type as part of the object schema. Realm Database automatically indexes primary key properties, which allows you to efficiently read and modify objects based on their primary key.

If an object type has a primary key, then all objects of that type must include the primary key property with a value that is unique among objects of the same type in a realm.

Note

Primary keys can be of type char, short, int, long, string, or MongoDB.Bson.ObjectId. Once you assign a property as a primary key, you cannot change it after an object of that type is added to a realm.

Property Schema

A property schema is a field-level configuration that defines and constrains a specific property in an object schema. Every object schema must include a property schema for each property in the object. At minimum, a property schema defines a property’s data type and indicates whether or not the property is required.

You can configure the following constraints for a given property:

Parameter Description
Type

Every property in a Realm object has a strongly defined data type. A property’s type can be a primitive data type or an object type defined in the same realm. The type also specifies whether the property contains a single value or a list of values.

Realm Database supports the following data types:

  • bool
  • short/int/long
  • float
  • double
  • decimal (see Using Decimal Values below)
  • char
  • string
  • DateTimeOffset
  • byte[]
  • ObjectId
  • IList<T>
Required Properties Non-nullable properties are always required, unless you specifically declare them with the optional type (int?, for example). To make nullable types like string and byte[] required, you mark the properties with the [Required] attribute. While a persisted IList<T> property can never be null, a IList<string> or IList<byte[]> may contain null values. If you want to ensure that these lists do not contain any null values, use the [Required] attribute on the list.
Indexed A property index significantly increases the speed of certain read operations at the cost of additional overhead for write operations. Indexes are particularly useful for equality comparison, such as querying for an object based on the value of a property. You identify the field(s) on which you want to index by using the [Indexed] attribute.

Using Decimal Values

Realm supports 128-bit decimal values with the Decimal128 Bson type. When defining a decimal type, you can use the Decimal128 Bson type or the .NET decimal type, even though it is only a 96-bit decimal. The SDK automatically converts between the two, although you risk losing precision or range. The following example shows how to use both the Decimal128 Bson type and the .NET decimal type:

public class MyClassWithDecimals : RealmObject
{
    // Standard (96-bit) decimal value type
    public decimal VeryPreciseNumber { get; set; }

    // 128-bit Decimal128 
    public Decimal128 EvenMorePreciseNumber { get; set; }
    public Decimal128 AnotherEvenMorePreciseNumber { get; set; }

    // Nullable decimal or Decimal128 are supported, too
    public decimal? MaybeDecimal { get; set; }
    public Decimal128? MaybeDecimal128 { get; set; }

    public void PlayWithDecimals()
    {
        var myInstance = new MyClassWithDecimals();
        // To store decimal values:
        realm.Write(() =>
        {
            myInstance.VeryPreciseNumber = 1.234567890123456789M;
            myInstance.EvenMorePreciseNumber = Decimal128.Parse("987654321.123456789");

            // Decimal128 has explicit constructors that take a float or a double
            myInstance.EvenMorePreciseNumber = new Decimal128(9.99999);
        });

        // To query decimal values:
        var largerThanFive = realm.All<MyClassWithDecimals>()
                                  .Where(o => o.VeryPreciseNumber > 5)
                                  .OrderBy(o => o.EvenMorePreciseNumber);

        var smallerThanZero = realm.All<MyClassWithDecimals>()
                                   .Where(o => o.EvenMorePreciseNumber < 0)
                                   .OrderByDescending(o => o.VeryPreciseNumber);
    }
}

Summary

  • Realm objects are of a type defined as you would any other class.
  • Realm objects are live: they always reflect the latest version on disk and update automatically when the underlying object changes.
  • A Realm object type may have a primary key property to uniquely identify each instance of the object type.
  • The Realm object’s schema defines the properties of the object and which properties are optional, which properties have a default value, and which properties are indexed.