更改对象模型 - .NET SDK
Overview
迁移将现有域及其对象从当前的 Realm 模式版本转换为较新的版本。 应用程序数据模型通常会随着时间的推移而变化,以适应新的需求和功能。 每当客户端应用程序升级到新版本时,迁移功能使您能够灵活地自动更新现有应用程序数据。
在下面的例子中,有一个名为“Person”的 RealmObject
:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FullName { get; set; } public int Age { get; set; } }
假设我们现在想要将 FullName
属性拆分为两个独立属性:FirstName
和 LastName
:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } }
此时,模型与任何已保存数据之间存在不匹配,当您尝试打开域时会出现异常。
模式版本
模式版本可标识 Realm 模式在某个时间点的状态。Realm 会跟踪每个 Realm 的模式版本,并使用该信息将每个 Realm 中的对象映射到正确的模式。
模式版本是指打开 Realm 时可包含在 Realm 配置中的整数。如果客户端应用程序在打开 Realm 时未指定版本号,则该 Realm 默认采用 0
版本。
重要
单调递增版本
迁移必须将 Realm 更新到更高的模式版本。如果客户端应用程序打开的 Realm 的模式版本低于该 Realm 的当前版本,或是指定的模式版本与该 Realm 的当前版本相同但包含不同对象模式,Realm 则会引发错误。
迁移模式
以下示例演示如何在模式中添加、删除和修改属性。 首先,进行所需的模式更改。 然后,创建相应的迁移函数,将数据从原始模式迁移到更新后的模式。
注意
Realm Open 上的版本更新
假设本示例中的每次模式更改均发生在应用程序已使用每个版本一段时间之后。仅当您打开具有已更新模式的域并显式指定新版本号后,新的模式版本号才适用,因此为了获得版本 3,您首先需要打开版本 1 和 2 的应用程序。
使用模式版本 1
的域具有 Person
对象类型:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FirstName { get; set; } public int Age { get; set; } }
添加属性
以下示例将LastName
属性添加到原始 Person 模式:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } }
删除属性
以下示例使用组合的FullName
属性,而不是原始 Person 模式中单独的FirstName
和LastName
属性:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FullName { get; set; } public int Age { get; set; } }
修改属性类型或重命名属性
以下示例修改了原始 Person模式中的Age
属性,将其重命名为Birthday
并将类型更改为DateTimeOffset
:
public partial class Person : IRealmObject { [ ] [ ] public ObjectId Id { get; set; } public string FullName { get; set; } public DateTimeOffset Birthday { get; set; } }
迁移功能
提示
在开发期间绕过迁移
在开发或调试应用程序时,您可能想要删除而不是迁移域。因模式不匹配而需要迁移时,请使用 ShouldDeleteIfMigrationNeeded 标志自动删除数据库。
切勿将此标记设为 true
的应用发布到生产环境。
要迁移域以符合更新的Person
模式,请将 Realm 的模式版本设立为FullName
4
并定义一个迁移函数,设立现有的FirstName
和LastName
属性以及Birthday
的值基于Age
:
1 var config = new RealmConfiguration 2 { 3 SchemaVersion = 4, 4 MigrationCallback = (migration, oldSchemaVersion) => 5 { 6 var oldVersionPeople = migration.OldRealm.DynamicApi.All("Person"); 7 var newVersionPeople = migration.NewRealm.All<Person>(); 8 9 // Migrate Person objects 10 for (var i = 0; i < newVersionPeople.Count(); i++) 11 { 12 var oldVersionPerson = oldVersionPeople.ElementAt(i); 13 var newVersionPerson = newVersionPeople.ElementAt(i); 14 15 // Changes from version 1 to 2 (adding LastName) will 16 // occur automatically when Realm detects the change 17 18 // Migrate Person from version 2 to 3: 19 // Replace FirstName and LastName with FullName 20 // LastName doesn't exist in version 1 21 var firstName = oldVersionPerson.DynamicApi.Get<string>("FirstName"); 22 var lastName = oldVersionPerson.DynamicApi.Get<string>("LastName"); 23 24 if (oldSchemaVersion < 2) 25 { 26 newVersionPerson.FullName = firstName; 27 } 28 else if (oldSchemaVersion < 3) 29 { 30 newVersionPerson.FullName = $"{firstName} {lastName}"; 31 } 32 33 // Migrate Person from version 3 to 4: replace Age with Birthday 34 if (oldSchemaVersion < 4) 35 { 36 var birthYear = 37 DateTimeOffset.UtcNow.Year - oldVersionPerson.DynamicApi.Get<int>("Age"); 38 newVersionPerson.Birthday = 39 new DateTimeOffset(birthYear, 1, 1, 0, 0, 0, TimeSpan.Zero); 40 } 41 } 42 } 43 }; 44 var realm = Realm.GetInstance(config);