Object Models - .NET SDK
On this page
Create an Object Model
Realm classes are regular C# classes that define the Realm schema.
Important
Inheritance
All Realm objects inherit from the
IRealmObject,
IEmbeddedObject, or
IAsymmetricObject
interface and should be declared partial
classes.
You can also derive from the RealmObject, EmbeddedObject, or AsymmetricObject base classes. However, in the future we may deprecate the base classes. You should use the interfaces for any new classes that you write.
Object Schema
An object schema is a configuration object that defines the properties and relationships of a Realm object. Realm client applications define object schemas with the native class implementation in their respective language using the Object Schema.
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 App has a App Services Schema composed of a list of object schemas for each type of object that the realms in that application may contain. 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.
Property Annotations
Schema properties are standard C# properties on a RealmObject
. There are
several property annotations that you can use to more finely define how a Realm
handles a specific property.
Primary Key
A primary key is a property that uniquely identifies an object. You can create a primary key with any of the following types (or their nullable counterparts):
ObjectId
UUID
string
char
byte
short
int
long
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
Once you assign a property as a primary key, you cannot change it.
The following example demonstrates how to designate a primary key in an object schema:
public partial class Dog : IRealmObject { [ ] public string Name { get; set; } public int Age { get; set; } public Person Owner { get; set; } }
Indexes
Indexes support the efficient execution of queries in Realm Database. Without indexes, Realm Database must perform a collection scan, i.e. scan every document in a collection, to select those documents that match a query. If an appropriate index exists for a query, Realm Database can use the index to limit the number of documents that it must inspect.
Indexes are special data structures that store a small portion of a realm's data in an easy to traverse form. The index stores the value of a specific property ordered by the value of the property. The ordering of the index entries supports efficient equality matches and range-based query operations.
Adding an index can speed up some queries at the cost of slightly slower write times and additional storage and memory overhead. Indexes require space in your realm file, so adding an index to a property will increase disk space consumed by your realm file. Each index entry is a minimum of 12 bytes.
You can index properties with the following types:
bool
byte
short
int
long
DateTimeOffset
char
string
ObjectId
UUID
To index a property, use the [Indexed] attribute:
public partial class Person : IRealmObject { [ ] public string Name { get; set; } public IList<Dog> Dogs { get; } }
Required and Optional Properties
In C#, value types are implicitly non-nullable, but can be made optional by appending
?.
Reference types, such as string
and byte[]
, are implicitly nullable and can be
made required by annotating them with the [Required]
attribute. Properties of types
that inherit from IRealmObject
or IEmbeddedObject
are special and can always be
null. Applying [Required]
on such a property will result in a compilation error.
You can use the [Required]
attribute as seen in the following example:
public partial class Person : IRealmObject { [ ] public string Name { get; set; } public IList<Dog> Dogs { get; } }
Default Field Values
You can use the built-in language features to assign a default value to a property. In C#, you can assign a default value in the property declaration.
public partial class Person : IRealmObject { public string Name { get; set; } = "foo"; }
Note
Default Values and Nullability
While default values ensure that a newly created object cannot contain
a value of null
(unless you specify a default value of null
),
they do not impact the nullability of a property. To make a property
non-nullable, see Required Properties.
Ignore a Property
If you don't want to save a property in your model to a realm, you can ignore that property. A property is ignored by default if it is not autoimplemented or does not have a setter.
Ignore a property from a Realm object model with the [Ignored] attribute:
// Rather than store an Image in Realm, // store the path to the Image... public string ThumbnailPath { get; set; } // ...and the Image itself can be // in-memory when the app is running: [ ]public Image Thumbnail { get; set; }
Rename a Property
By default, Realm Database uses the name defined in the model class to represent properties internally. In some cases you might want to change this behavior:
To make it easier to work across platforms, since naming conventions differ.
To change a property name in .NET without forcing a migration.
Choosing an internal name that differs from the name used in model classes has the following implications:
Migrations must use the internal name when creating classes and properties.
Schema errors reported will use the internal name.
Use the [MapTo] attribute to rename a property:
public partial class Person : IRealmObject { [ ] public string Name { get; set; } }
Rename a Class
By default, Realm Database uses the name defined in the model class to represent classes internally. In some cases you might want to change this behavior:
To support multiple model classes with the same simple name in different namespaces.
To make it easier to work across platforms, since naming conventions differ.
To use a class name that is longer than the 57 character limit enforced by Realm Database.
To change a class name in .NET without forcing a migration.
Use the [MapTo] attribute to rename a class:
[ ]public partial class Person : IRealmObject { public string Name { get; set; } }
Custom Setters
Realm will not store a property with a custom setter. To use a custom setter,
store the property value in a private property and then
map that value to a public property with the custom setter. Realm will store the
private property, while you modify its value via the public property.
In the following code, the private email
property is stored in the realm,
but the public Email
property, which provides validation, is not persisted:
// This property will be stored in the Realm private string email { get; set; } // Custom validation of the email property. // This property is *not* stored in Realm. public string Email { get { return email; } set { if (!value.Contains("@")) throw new Exception("Invalid email address"); email = value; } }
Omit Classes from your Realm Schema
By default, your application's Realm Schema includes all
classes that implement IRealmObject
or IEmbeddedObject
.
If you only want to include a subset of these classes in your Realm
Schema, you can update your configuration to include the specific classes you want:
// Declare your schema partial class LoneClass : IRealmObject { public string Name { get; set; } } class AnotherClass { private void SetUpMyRealmConfig() { // Define your config with a single class var config = new RealmConfiguration("RealmWithOneClass.realm"); config.Schema = new[] { typeof(LoneClass) }; // Or, specify multiple classes to use in the Realm config.Schema = new[] { typeof(Dog), typeof(Cat) }; } }
Data Binding and MVVM
When building a MAUI/Xamarin app using the MVVM pattern, you often want proper data binding in both directions between the View and ViewModel: if a property value changes in the UI, the ViewModel should be notified, and vice-versa. ViewModels typically implement the INotifyPropertyChange interface to ensure this.
However, when you bind UI elements to a RealmObject, this notification happens automatically, thus greatly simplifying your ViewModel code.
You can also bind a UI element to a realm Live Query.
For example, if you bind a
ListView
to a live query, then the list will update automatically when the results of the
query change; you do not need to implement the INotifyPropertyChange
interface.
For example, if you bind a ListView to a query that returns all Product objects, the list of available products updates automatically when a product is added, changed, or removed from the realm:
// Somewhere in your ViewModel AllProducts = realm.All<Products>();
<!-- Somewhere in your View --> <ListView ItemsSource="{Binding AllProducts}">