Schema migration problem


#1

Hi and thanks in advance.
I have to migrate the schema on a mobile app and I don’t understand how to do this in a good way.
I try to post the old schema and the new one with the differences in two objects, Node is the father.

OLD:

public class Node : RealmObject
{
	[PrimaryKey]
	public int IdNodeJobItem { get; set; }
	
	//...lots of other properties
	
	public IList<DocumentTypeMandatoryValue> DocumentTypeMandatoryValues { get; }
	
	//...lots of other properties	
}

public class DocumentTypeMandatoryValue : RealmObject
{
	[PrimaryKey]
	public byte IdDocumentTypeMandatoryValue { get; set; }
	public byte IdDocumentType { get; set; }
	public bool IsMandatory { get; set; }
}

NEW:

public class Node : RealmObject
{
	[PrimaryKey]
	public int IdNodeJobItem { get; set; }

	//...lots of other properties

	public IList<LinkedDocumentType> LinkedDocumentTypes { get; }

	//...lots of other properties	
}

public class LinkedDocumentType : RealmObject
{
	[PrimaryKey]
	public short IdLinkedDocumentType { get; set; }
	public byte IdDocumentType { get; set; }
	public bool IsMandatory { get; set; }
	public byte? IdOptionalDocumentType { get; set; }
}

So as you can see I need to rename the property which represents the relationship and also I need to rename the child (+ add a new nullable property).
I also need to preserve the relationship for old nodes.
How I can do this inside a migration callback?


#2

I believe that when you rename a class, it’s gone, so you can’t really “preserve” the relationships it was a part of. So here’s some code as an inspiration (note that I haven’t tested it and it may have compilation errors):

var documentTypeMandatoryValues = migration.OldRealm.All("DocumentTypeMandatoryValue");
foreach (var documentTypeMandatoryValue in documentTypeMandatoryValues)
{
    migration.NewRealm.Add(new LinkedDocumentType
    {
        IdLinkedDocumentType = (short)IdDocumentTypeMandatoryValue, // ???
        IdDocumentType = documentTypeMandatoryValue.IdDocumentType,
        IsMandatory = documentTypeMandatoryValue.IsMandatory,
        ...
    });
}

foreach (var node in migration.NewRealm.All<Node>())
{
    var oldNode = migration.OldRealm.Find("Node", node.IdNodeJobItem);
    foreach (var item in oldNode.DocumentTypeMandatoryValues)
    {
        var newItem = migration.NewRealm.Find<LinkedDocumentType>(item.IdDocumentTypeMandatoryValue);
        node.LinkedDocumentTypes.Add(newItem);
    }
}

#3

Thank you Nikola, I understand the idea but as you said the code doesn’t compile because the Find method returns a RealmObject but I need a dynamic. Is there a way to have it? Otherwise I can match old and new node using the ElementAt().


#4

Hm… you’re right. I guess you could invert it then:

foreach (var oldNode in migration.OldRealm.All("Node"))
{
    var node = migration.NewRealm.Find<Node>(node.IdNodeJobItem);
    ...
}