Realm-dotnet: Updating of inner object rather adds a new object and replace the old one than updates it

Created on 4 Feb 2020  Â·  8Comments  Â·  Source: realm/realm-dotnet

Not sure is it bug or feature but it looks unexpected to me:

Expected Results

Console output:

Kristian[2]
0 = Rex
1 = Тузик

Actual Results

Kristian[3]
0 = Rex
1 = Тузик
1 = Тузик

Code Sample

public class Person : RealmObject
{
    [PrimaryKey]
    public int Id { get; set; }

    public string Name { get; set; }

    public IList<Dog> Dogs { get; }
}
public class Dog : RealmObject
{
    [PrimaryKey]
    public int Id { get; set; }
    public string Name { get; set; }
}

and usage:

var realm = Realm.GetInstance();
realm.Write(() => realm.RemoveAll());
var dog1 = new Dog
{
    Id = 0,
    Name = "Rex"
};
var dog2 = new Dog
{
    Id = 1,
    Name = "Bethoven"
};
Person k = new Person
{
    Id = 1,
    Name = "Kristian",
    Dogs = { dog1, dog2 }
};
realm.Write(() => realm.Add(k));
var dog3 = new Dog
{
    Id = 1,
    Name = "Тузик"
};
realm.Write(() =>
{
    realm.Add(dog3, true);
    k.Dogs.Add(dog3);
});
Console.WriteLine($"{k.Name}[{k.Dogs.Count}]");
foreach (var dog in k.Dogs)
    Console.WriteLine($"{dog.Id} = {dog.Name}");

Version of Realm and Tooling

Realm: 4.2.0

Related:

If one adds the same object to the inner collection then count of objects will be increases as well.

O-Community T-Help

Most helpful comment

For what it's worth, I think the behavior you expect here is that of a Set<T>. While lists in Realm do not have set semantics, we're considering adding a Set datatype which models to-many relationships with set semantics.

All 8 comments

That's expected - a list can hold multiple references to the same object. realm.All<Dog>().Count() should still be 2, however.

yeah, thank you.

Closing issue since this is not a bug. Though I still think it will be nice to document it explicitly.

Just curious: how one can remove all "duplicate" references?

The same way you would with any other IList<T> implementation:

while (list.Contains(item))
{
    list.Remove(item);
}

For what it's worth, I think the behavior you expect here is that of a Set<T>. While lists in Realm do not have set semantics, we're considering adding a Set datatype which models to-many relationships with set semantics.

awesome, thank you

You could also model set semantics using the inverse relationships feature.

Thank you. I was suggested that already but I'm still unsure how to apply it.
Something like that?

public class Dog : RealmObject
{
    [PrimaryKey]
    public int Id { get; set; }
    public string Name { get; set; }
    [Backlink(nameof(Person.Dogs))]
    public IQueryable<Person> Owner { get; }
}

and usage:

var dogs = realm.All<Dog>().ToArray().Where(d => d.Owner.First().Id == k.Id);

The model would look something like:

public class Dog : RealmObject
{
    public Person Owner { get; set; }
}

public class Person : RealmObject
{
    [Backlink(nameof(Dog.Owner))]
    public IQueryable<Dog> Dogs { get; }
}

So if you have a person var myPerson = realm.All<Person>().FirstOrDefault(p => p.Id == 123), then the myPerson.Dogs collection will contain exactly one entry for each dog that has dog.Owner == myPerson.

Was this page helpful?
0 / 5 - 0 ratings