Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

对象模型 - .NET SDK

在此页面上

  • 创建对象模型
  • 对象模式
  • 属性注解
  • 主键
  • 索引
  • 全文搜索索引
  • 默认字段值
  • 忽略属性
  • 为属性重命名
  • 重命名类
  • 自定义 Setter
  • 定义非结构化数据
  • 从 Realm 模式中省略类
  • 必要属性和可选属性
  • 忽略无效性

Realm 类是定义 Realm 模式的普通 C# 类。

重要

继承

所有Realm对象都继承自 IRealmObjectIEmbeddedObjectIAsymmetricObject接口,并且必须声明为 partial类。

在早于10.18.0的 .NET SDK 版本中, 派生自RealmObjectEmbeddedObjectAsymmetricObject基类的对象。 这种 Realm 模型定义方法仍然受支持,但不包括可空性注解等新功能。 在未来的 SDK 版本中,基类将被弃用。 您编写的任何新类都应使用接口,并应考虑迁移现有类。

注意

类名不得超过 57 个 UTF-8 字符。

对象模式是定义 Realm 对象属性和关系的配置对象。Realm 客户端应用程序使用“Object Schema”(对象模式),以相应的语言通过原生类实现来定义对象模式。

对象模式指定对对象属性的约束,例如每个属性的数据类型以及是否需要属性。模式还可以定义 Realm 中对象类型之间的关系

每个应用程序都有一个App Services Schema,由该应用程序可能包含 Realm 的每种类型对象的对象模式列表组成。Realm 保证所有 Realm 对象都符合对象类型的模式,并在创建、修改或删除对象时对其进行验证。

模式属性是RealmObject上的标准 C# 属性。您可以使用多个属性注解来更精细地定义 Realm 如何处理特定属性。

主键是一个唯一标识对象的属性。您可以使用以下任何类型(或其可为 null 的对应项)创建主键:

  • ObjectId

  • UUID

  • string

  • char

  • byte

  • short

  • int

  • long

您可以在对象类型的单个属性上定义主键,作为对象模式的一部分。Realm 会自动为主键属性建立索引,因此您可以根据主键高效地读取和修改对象。

如果某个对象类型具有主键,则该类型的所有对象都必须包含主键属性,并且在 Realm 中相同类型的对象中,该主键属性具有唯一值。

注意

一旦将某个属性指定为主键,就无法对其进行更改。

以下示例演示了如何在对象模式中指定主键:

public partial class Dog : IRealmObject
{
[PrimaryKey]
public string Name { get; set; }
public int Age { get; set; }
public Person? Owner { get; set; }
}

提示

另请参阅:

索引显著缩短了 Realm 中的查询时间。如果没有索引,Realm 会扫描集合中的每份文档,从而选择与给定查询匹配的文档。但是,如果查询存在适用的索引,Realm 将使用该索引来限制必须检查的文档数量。

您可以为以下类型的属性建立索引:

  • bool

  • byte

  • short

  • int

  • long

  • DateTimeOffset

  • char

  • string

  • ObjectId

  • UUID

注意

添加索引可以加快某些查询的速度,但代价是写入速度稍慢,并增加存储和内存开销。索引需要 Realm 文件的空间,因此为属性添加索引会增加 Realm 文件消耗的磁盘空间。每个索引条目至少有 12 个字节。

要为属性建立索引,请使用Indexed属性。 通过Indexed属性,您可以使用IndexType枚举指定属性的索引类型。 在以下示例中,我们在Name属性上设置了默认(“常规”)索引:

public partial class Person : IRealmObject
{
[Indexed(IndexType.General)]
public string Name { get; set; }
[Indexed(IndexType.FullText)]
public string Biography { get; set; }
}

注意

创建索引时,您是在本地 Realm 而不是在 Atlas 集合上创建索引。 如果您需要直接查询 Atlas 集合并希望提高性能,请参阅创建、查看、删除和隐藏索引。

除了标准索引外,Realm 还支持对 string 属性创建 Atlas 全文搜索索引。虽然无论是否使用标准索引都可以查询字符串字段,但 FTS 索引支持搜索多个词汇和短语并排除其他。

有关查询全文索引的详情,请参阅全文搜索 (LINQ)全文搜索 (RQL)

要为 FTS 属性建立索引,请将Indexed属性与IndexType.FullText枚举一起使用。 在以下示例中,我们在Biography属性上建立了FullText索引:

public partial class Person : IRealmObject
{
[Indexed(IndexType.General)]
public string Name { get; set; }
[Indexed(IndexType.FullText)]
public string Biography { get; set; }
}

您可以使用内置语言功能为属性指定默认值。在 C# 中,您可以在属性声明中为基元指定默认值。您不能对集合设置默认值,除非将其设置为 null!。即使将集合设置为 null!,集合也始终会在首次访问时初始化,因此永远不会为 null。

public partial class Person : IRealmObject
{
public string Name { get; set; } = "foo";
public IList<PhoneNumber> PhoneNumbers { get; } = null!;
}

注意

默认值和可空性

虽然默认值可确保新创建的对象不能包含值null (除非您指定默认值null ),但它们不会影响属性的可空性。 要将属性设为不可为空,请参阅必需属性。

如果您不想将模型中的某个属性保存到 Realm,则可以忽略该属性。如果属性不是自动实现的或没有 setter,则默认情况下将忽略该属性。

使用 Ignore 属性,忽略 Realm 对象模型中的属性:

// 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:
[Ignored]
public Image? Thumbnail { get; set; }

默认情况下,Realm 在内部使用模型类中定义的名称来表示属性。在某些情况下,您可能想要更改此行为:

  • 要便于在具有不同命名约定的多个平台上工作。

  • 在不强制迁移的情况下更改 .NET 中的属性名称。

选择与模型类中使用的名称不同的内部名称,会产生以下影响:

  • 在创建类和属性时,迁移必须使用内部名称。

  • 模式错误报告将使用内部名称。

使用[MapTo]属性重命名属性:

public partial class Person : IRealmObject
{
[MapTo("moniker")]
public string Name { get; set; }
}

默认情况下,Realm 在内部使用模型类中定义的名称来表示类。在某些情况下,您可能想要更改此行为:

  • 支持在不同命名空间中具有相同简单名称的多个模型类。

  • 要便于在具有不同命名约定的多个平台上工作。

  • 要使用长度大于 Realm 执行的 57 个字符限制的类名。

  • 更改 .NET 中的类名称而不强制迁移。

使用[MapTo]属性重命名类:

[MapTo("Human")]
public partial class Person : IRealmObject
{
public string Name { get; set; }
}

Realm 不会使用自定义 setter 存储属性。 若要使用自定义 setter,请将属性值存储在私有属性中,然后使用自定义 setter 将该值映射到公共属性。 Realm 将存储私有属性,而您则通过公共属性修改其值。 在以下代码中,私有email属性存储在 Realm 中,但提供验证的公共Email属性不会保留:

// 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;
}
}

12.2.0版本新增

从 SDK 版本12.2.0开始, 您可以在RealmValue属性中存储混合数据的集合。 您可以使用此功能对复杂的数据结构(例如JSON或MongoDB文档)进行建模,而无需定义严格的数据模型。

非结构化数据是指不容易符合预期模式的数据,因此对单个数据类进行建模很困难或不切实际。 示例,您的应用可能具有高度可变的数据或动态数据,其结构在运行时未知。

将集合存储在混合属性中可在不牺牲功能的情况下提供灵活性,包括使用Device Sync时的性能同步。 您可以像使用非混合集合一样使用它们:

  • 您最多可以嵌套100级混合集合。

  • 您可以对混合集合的React进行查询和响应。

  • 您可以查找并更新单个混合集合元素。

但是,与使用结构化模式或将JSON blob 序列化为单个string属性相比,在混合集合中存储数据的性能较低。

要对应用中的非结构化数据进行建模,请在模式中将相应属性定义为RealmValue类型。 然后,您可以设立这些RealmValue属性设置为RealmValue元素的列表字典。 请注意, RealmValue不能表示设立或嵌入式对象。

提示

  • 当类型未知但每个值都有唯一标识符时,请使用混合数据类型的映射。

  • 当类型未知但对象的顺序有意义时,请使用混合数据类型的列表。

默认情况下,您的应用程序的 Realm 模式包括实现IRealmObjectIEmbeddedObject的所有类。如果您只想在 Realm 模式中包含这些类的子集,则可以更新配置以包含所需的特定类:

// 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) };
}
}

在C#中,值类型(例如intbool )是隐式不可为 null 的。但是,可以使用问号 (? ) 表示法将它们设为可选。

从 C# 8.0 开始,引入了可空引用类型。如果您的项目使用的是 C# 8.0 或更高版本,您还可以使用 ? 将引用类型(如 stringbyte[])声明为可空。

注意

从 .NET 6.0开始,新项目默认启用可空上下文。 对于较旧的项目,您可以手动启用它。 有关详细信息,请参阅 https://learn.microsoft.com/en-us/dotnet/csharp/ language-reference/builtin-types/nullable-reference-types#setting-the-nullable-context。

Realm.NET SDK 完全支持可空感知的上下文,并使用可空性来确定属性是必要还是可选属性。SDK 有以下规则:

  • 如果您不将值类型和引用类型属性指定为可为 null,则 Realm 假定这些属性均为必填。如果您使用 ? 将其指定为可为 null,则 Realm 会将其视为可选。

  • 必须将 Realm 对象类型的属性声明为可为 null。

  • 您不能将集合(列表、集合、反向链接和字典)声明为可为 null,但根据以下规则,它们的参数可为 null:

    • 对于所有类型的集合,如果参数是基元(值类型或引用类型),则它们可以为必填或可以为 null。

    • 对于列表、集合和反向链接,如果参数是 Realm 对象,则它们不能为 null。

    • 对于值类型为 Realm 对象的字典,必须将值类型参数声明为可为 null。

以下代码片段演示了这些规则:

#nullable enable
public partial class Person : IRealmObject
{
/* Reference Types */
public string NonNullableName { get; set; }
public string? NullableName { get; set; }
public byte[] NonNullableArray { get; set; }
public byte[]? NullableArray { get; set; }
/* Value Types */
public int NonNullableInt { get; set; }
public int? NullableInt { get; set; }
/* Realm Objects */
public Dog? NullableDog { get; set; }
// public Dog NonNullableDog { get; set; } // Compile-time error
/* Collections of Primitives */
public IList<int> IntListWithNonNullableValues { get; }
public IList<int?> IntListWithNullableValues { get; }
// public IList<int>? NullableListOfInts { get; } // Compile-time error
/* Collections of Realm Objects */
public IList<Dog> ListOfNonNullableObjects { get; }
// public IList<Dog>? NullableListOfObjects { get; } // Compile-time error
// public IList<Dog?> ListOfNullableObjects { get; } // Compile-time error
public ISet<Dog> SetOfNonNullableObjects { get; }
// public ISet<Dog>? NullableSetOfObjects { get; } // Compile-time error
// public ISet<Dog?> SetOfNullableObjects { get; } // Compile-time error
public IDictionary<string, Dog?> DictionaryOfNullableObjects { get; }
// public IDictionary<string, Dog> DictionaryOfNonNullableObjects { get; } // Compile-time error
// public IDictionary<string, Dog>? NullableDictionaryOfObjects { get; } // Compile-time error
[Backlink(nameof(Dog.Person))]
public IQueryable<Dog> MyDogs { get; }
// [Backlink(nameof(Dog.People))]
// public IQueryable<Dog?> MyDogs { get; } // Compile-time error
}

注意

如果您使用的是较旧的模式类型定义(您的类派生自RealmObject基类),或者您没有启用可空性,则需要对任何必需的stringbyte[]使用[Required]属性。属性。

您可能希望更灵活地定义 Realm 对象中属性的可空性。 您可以通过在realm.ignore_objects_nullability = true 全局配置文件 中设置 来实现此目的。

如果您启用 realm.ignore_objects_nullability,则 Realm 对象属性(包括 Realm 对象集合)上的可空性注释将被忽略。

后退

模型数据