I have the following model defined in .NET:
Public Class Request
<Key()>
Public Property RequestId As String
Public Property Description As String
Public Property InfoCards As List(Of InfoCard)
End Class
Public Class InfoCard
<Key()>
Public Property InfocardId As String
Public Property Description As String
Public Property RequestId As String
End Class
The ReqeuestId property on the InfoCard is so that EF Code First can generate the db.
I then use the UpshotContext
helper to generate the JavaScript model like so:
Html.UpshotContext(bufferChanges:= true) _
.DataSource(Of UpshotTest.UpshotTest.RequestController)(Function(x) x.GetRequests()) _
.ClientMapping(Of UpshotTest.Models.Request)("Request") _
.ClientMapping(Of UpshotTest.Models.InfoCard)("InfoCard")
This generates all models nicely, and when I call refresh
on the upshot dataSource, the data is retrieved as expected.
The problem I am facing is when I attempt to modify a property of a child object (e.q. Request.InfoCards(0).Description
). Changing that value will trigger the change in the InfoCard
, but not in the Request
entity. So, calling Request.IsUpdated()
will return false, whilst calling Request.InfoCards(0).IsUpdated()
will return true.
Does upshot not know how to track changes in child entities? Or is it a problem with the mappings on the client side? So far I have tried several mappings:
mapping all properties manually:
window.Request = function (initialData) {
var self = this;
self.RequestId = ko.observable(initialData.RequestId);
self.Description = ko.observable(initialData.Description);
self.InfoCards = ko.observableArray(ko.utils.arrayMap(initialData.InfoCards, function (data) {
return new window.InfoCard(data);
}));
upshot.addEntityProperties(self, "Request:#UpshotTest.Models");
};
using upshot.map
:
window.Request = function (initialData) {
var self = this;
upshot.map(initialData, upshot.type(Request), self);
};
defining my own map function and passing it to upshot:
window.Request = function (initialData) {
var self = this;
upshot.observability.configuration.map(initialData, upshot.type(Request), map, self);
};
The mappings seem correct with all approaches, except the parent entity is not aware of modifications done in its children. Is child tracking even possible?
Okay, I found the issue in the end. As it turns out, this behavior was reproducible when a hierarchy of 3 nested entities existed (i.e. Request -> InfoCard -> InfoField. Modifying a value of the InfoField did not reflect in the parent entity.
After many hours of upshot debugging, I found the culprit to be the _addTrackingRecursive
method in upshot.js. Replacing the obs.track(obj, this._getTracker(), this._entityType);
call to obs.track(obj, this._getTracker(), type);
solved the nested change tracking issue.