redarrowlabs / Argo

:squirrel: c# object => json.api relational mapping
MIT License
7 stars 3 forks source link

investigate moving away from model Patch property #64

Closed engenb closed 6 years ago

engenb commented 7 years ago

the Model acts like a proxy for the underlying Resource. Each setter calls into the session, which in tern updates the source Model's Patch with depending on what changed.

this falls down when dealing with [Property]s that are ICollection. When collections are mutated by adding/removing items, the session is not informed because this was not done through a Model setter, thus the Patch is not correct.

an ideal approach would be to get the current state of the object by converting it to a Resource JObject, and then doing a diff against the Resource since the last request to the server.

zeitlerc commented 6 years ago

Argo only tracks the 1st level of properties. The code/test below would fail because Argo does not track anything in the Address property. On order to update the properties in Address, a new instance of the Address class would need to be created and set on the Address property so the setter picks up the change. It's a slightly different issue than the Collections, but would be also fixed with the JObject diff approach.

[Model]
public class Person 
{
    [Id]
    public Guid Id { get;set; }
    [Property]
    public Address Address { get;set; }
}
public class Address 
{
    public string Street { get;set; }
    public string City { get;set; }
}

Guid crossSessionId;
using (var session = SessionFactory.CreateSession())
{
    var person = new Person
    {
        Address = new Address 
        {
            Street = "Old Street"
        }
    };
    person = await session.Create(person);
    crossSessionId = person.Id;
}
// update!
using (var session = SessionFactory.CreateSession())
{
    var person = await session.Get<Person>(crossSessionId);
    person.Address.Street = "New Street";
    await session.Update(person);
}
// later that day...
using (var session = SessionFactory.CreateSession())
{
    var person = await session.Get<Person>(crossSessionId);
    // FAILS!!!
    Assert.Equal("New Street", person.Address.Street);
}