2
votes

Each time I think I have it nailed, it rears its head again!

So simply if there's a master table with navigation property to a collection of children and I use "createEntity" to create a new empty version of the entity I am able to see the navigation property in the entity returned, but I am unable to access/set any properties. I suspect this is because the parent key does not yet exist in the child entity?

To clarify. I can put in a breakpoint at the point where the new entity is returned and if I inspect the master() entity I can see the children property right there. If I then try and do:

master().children.childProperty("this is a new value")

...then I simply get "object function observable()..." (then loads of code from knockout I think) and ending "has no method 'childProperty'"

I think I've tried every combination of parentheses known to man and I get slightly different errors but nothing works. Do I need to have a [0] in there somewhere as "children" is effectively an array?

Added info for clarification.

As detailed in comments below, retrieving an existing entity with "expand" specified in the query for eager loading returns a master entity with a related child entity, properties of which I can set with the method I was trying to for the "new" example above which doesn't work. The specified length of the "children" collection when I return an existing master/child is 1, when I initialize a new master/child the array length is zero.

This isn't, I suppose, a traditional master/child relationship - it's more an associated entity than a child. To explain, "master" will always have one child record - think of it as master being a bottle and child being the related record that determines the colour of the bottle, the contents and the label details on the bottle. There will only ever be one bottle but there could be dozens of variations of colour, content and label.

When I retrieve an existing master record, I also specify the specific child I want so in this page I will only ever retrieve one master and one child record as I'm editing the specific variation and may want to change the label text.

In another page, I list all the variations for a bottle, so there I retrieve a master and all the associated children in a classic "one to many" example.

The model is:

Public Class bMaster
    Public Property ID() As Integer

    ...other properties

    Public Overridable Property bChildren() As ICollection(Of bChild)
End Class

Public Class bChild
    Public Property ID() As Integer
    Public Property bMasterID() As Integer

    ...other properties

    Public Overridable Property bMaster() As bMaster
End Class
1

1 Answers

4
votes

Carl - Kick yourself. You are so close that it hurts to write this for you. If children is a collection you can't simply set a value for each one of them like that. Since they are an array you must select one of them to set a value on.

var child = master().children()[0]; // get the first child
child.childProperty(someValue);

This would also work this way -

ko.utils.arrayForEach(master().children(), function (child) {
    child.childProperty(someValue);
});

Which would loop through your array and set the value for each of the entities in the collection.

Edit

If it is a new entity then it doesn't yet have a child entity. If there is always only going to be one child entity of the parent, I am not sure why you are using a collection instead of a complex type or something. You need to create a parent and then create a child on that parent as well -

var parentEntity = manager.createEntity('Parent');
var childEntity = manager.createEntity('Child');
childEntity.parent(parentEntity);
return childEntity;

Then if you wanted to set a property on a parent's child you would do so as I mentioned above -

var child = master().children()[0]; // get the first child
child.childProperty(someValue);

or you could still use

master().children()[0].childProperty(someValue);

Last, if you created the relationship properly (one to one instead of one to many) you could use this -

master().children().childProperty(someValue);