Correct method for adding master/child entity in breeze? - breeze

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

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);

Related

Breeze entityManager importEntities duplicating updated child entities

I am trying to use the "sandbox editor" approach with exportEntities and importEntities as detailed in the Cool Breezes section (and in many SO posts).
I have a main/parent entity which has one or more child entities. I have an HTML view (using Aurelia but that doesn't matter) that displays the 4 properties from the parent entity and then 3 or 4 properties from each of the child entities. In this example the parent has just one child entity.
The view uses a new entityManager and the parent/child entities have been imported from the 'master' entityManager in the usual export/import way. So far so good.
I edit one of the properties on the child entity and save it. I pass the saveResult to a copy of the updateMasterWithSaveResult. Everything works fine up to the line masterEm.importEntities(exported);
imports[] contains just one updated child entity - correct.
deletes[] is empty - correct.
exported contains the updated child entity info - correct.
masterEm contains the original parent and the original (non-updated) child - correct.
The problem
After it has called masterEm.importEntities(exported), masterEm now contains the original parent BUT the child property array now has 2 elements in it and both of them are the same, updated, child element. They are identical - same key, same everything.
Analysis
After much tracing I've narrowed this down to _linkRelatedEntities in a50_entityManager.js. At the bottom of this function it handles the foreign keys of the child and calls parent.getProperty(invNp.name).push(entity) or parent.getProperty(invNp.name)._push(entity) but
doesn't appear to check if the child is already connected. So in this case the child entity is
already in the array but gets added a second time.
Question: Is this the expected outcome? And, if so, am I missing something or is there a 'proper' way around it so that I end up with only one child element?
My temporary solution is to run a de-duplication on the child array after running importEntities but that seems hacky to say the least.

In DDD, how to create/edit domain ValueObjects ASP.NET MVC?

We have identified a Location entity in a database as a value object in our domain (DDD). Locations are used by other domain objects, but don't really "stand alone" -- they always belong to another entity.
Now we are trying to edit a list of these values in a simple MVC web application. So the view would show a list of locations in a view model LocationViewModel.
However, the value object is by definition immutable, yet does hold a reference to another entity (Business).
Domain:
public class Location : ValueObject<Location>
{
readonly locationId;
public int LocationId {get{return _locationId;}}
public Business Business {get;set;}
}
My problem is understanding how you can simply edit a bunch of value objects in a UI and change, e.g. what Business the location belongs to.
A value object is not supposed to have an "identity", but it does need an ID so the repository can update the database.
I also don't think you can make Location an entity just because you want to edit it in the UI. Or is Location, in this scenario indeed an Entity?
What am I not understanding?
Thank you!
It's a classic problem. In one context it's an entity and in another a value object. I found the example of a telephone number helpful to understanding this sort of problem.
In a CRM for example, a telephone number is a value object. The same one can be associated with multiple contacts. It varies by value (key concept here). So in this context it's a value object. In this example, I could store telephone numbers in the database and the 'ID' would be the telephone number itself. If the value object was made up of multiple parts then they would form a composite key.
If however we looked at a telephone number at a telephone company. That would most likely be an Entity. It could have all manor of information attached to it. All that info would vary by ID (which in this case would be the number).
In your case, Location sounds like a value object. If you need to save it in a database as a thing rather than just as part of an entity then use it's parts as a composite key. You will need to handle what happens when you 'change' one as it's not a change but the creation of new value object. One approach is to remove the old and insert the new. Or just keep all versions. It depends on your domain.
Hope that's helpful.
You don't change a value object. You create a new one with different values. If the value object has few properties that you want often to change, some helper methods are usefull. myObject.WithX(4711) will create a new instance with all properties the same as myObject but the X Property changed to 4711 for example.
To "edit" a value object in an UI you use a viewmodel. The Viewmodel is not a value object (and no entity by the way) and is not part of your domain. It's purely in the Presentation Layer. It is editable and mutable. It could have a constructor, taking your (immutable) value object to copy its values from and it could have a ToXXX Method to create a new (immutable) value object with its current (and changed) values.
If you want to store your value objects in a separate table (instead of roll out the fields in the table that stores the owning entity) this is purely data access layer related and not part of your domain model. This could be done by mapping. In the value object the database id is immutable and has no meaning in the domain model.

How to check if a parent entity contains sub entities in core data?

I have created a model in Core Data as given below :-
It shows that there are Categories that contain Contacts that further contain Phone Numbers and Email Addresses .
Now I need to know how will I check if the Parent entity has various sub entities in the CategoryTable ?
How do I perform a fetch request that will separate the parent entities from the sub entities and tell me which sub entities are of which parent entities ?
What kind of filter predicate should be used in this case ?
The Category model you have allows you to create a hierarchy of infinite depth so a parent object can also be a child object.
You need to traverse the hierarchy using the following approach:
Root level objects should always have parent = nil so your tope level predicate would simply be "parent == nil".
Then for each root object you can get its children by simply using "parent == %#", parentObject
You may want to use a UITableView to show each level in the hierarchy and so just add a property in the tableViewController that contains the parentObject and when you select a row push a new instance of the viewController.

What's the correct way to handle new breeze entities that might be thrown away?

I'm sure I've created my own pain here, but I'm struggling to understand the correct sequence of events to manage creating new entities in my scenario.
In my model I have two objects, ObjectA and ObjectB that both inherit from BaseObject, obviously each with their own additional properties.
In my view, as most of the information is the same, I want the user to be able to just select an option as to which one to create. So they fill out SharedProperty1 and SharedProperty2 (which is a collection navigation property), select an option as to if they want an A or B object, and then fill in a final page which has the last object specific properties.
As I didn't know which entity to create until the user had selected this option, I built a an object in the viewmodel to handle this temporary data. As part of that while they are filling out SharedProperty2 (the collection), as they add new ChildObjects, I create them with entityManager.createEntity('ChildObject'). Then when they reach the end, I create either ObjectA or ObjectB entity and add the child entitites (and other properties) and then try and save.
The problem is it never saves correctly, but I get different results depending on which approach I take. So because the user could just abort the new object process, I was creating the ChildObjects with EntityState.Detached because I thought that would be easier if they got thrown away. I realised though that all the entities created in this way get the id key 0. So then I fixed the keys while I was adding the ChildEntites to the parent (either ObjectA or ObjectB), by assigning them decreasing negative numbers (ie: -1, -2, etc). This resulted in some crazy server-side behaviour with only some entities being saved to the db and complaints of conflicting foreign keys.
This also had a bad smell that I hadn't understood this correctly, and I'd made a mess of it. So now I tried just creating the entities normally (ie: without the Detached flag), and they all get their own unique keys (again breeze appears to follow -1, -2, etc), but now when I try to copy them from my temporary viewmodel collection to the parent object collection, I get the error that an entity with this key is already attached. So now I can't even build up the correct model to save.
I still think I've not understood quite correctly how to handle this, so some pointers would be deeply appreciated.
To head off what I suspect will be a question, why I didn't use RejectChanges to handle the entities being thrown away. Basically a user can add a ChildObject (object gets created by breeze entityManager, added to viewmodel collection, bound to UI), and then decide to just remove it again (currently just gets removed from viewmodel collection) before they save their data. If I used reject changes I would throw away other important entites. I think I'm now going to be a good boy and use the proper detach method if someone removes the ChildObject in the view.
If I understand your question correctly, you are trying to create some properties and then add them to a parent objects collection when saving. Correct me if I am wrong, but Breeze not only supports this, but does so very efficiently. Having come from .NET and C# it was very difficult for me to grasp how easy this can be, but this is what I would do if I were you -
var childA = ko.observable();
var childB = ko.observable();
childA(entityManager.createEntity('ChildObject')); // populate your children
childB(entityManager.createEntity('ChildObject')); // populate your children
Then you can edit them in your view, and when you are ready to save simply add them to the collection.
var save = function() {
isSaving(true);
var parent = ko.observable();
return entityManager.getParent(parent, parentId)
.then(setParents)
.fail(catchError);
function setParents() {
childA().parent(parent());
childB().parent(parent());
entityManager.saveChanges()
.then(complete)
.fail(catchError);
function complete() {
isSaving(false);
return Q.resolve(); // Don't know if you have any unresolved conflicts
}
}
};
Basically in this manner we are -
A : Creating the entities
B : Editing them without performing any changes
C : When we call save we are setting their parent navigation property. In my prior ways (be it right or wrong) I would have simply set ParentId(parentId) and let EF figure out how to navigate but (pardon the pun) this is a breeze with Breeze. We could also just as easily pass in a parent observable and not have to go get it from the manager, it just depends on whether we have it already or not.
Another way you could do this if you want to manage the entities separately is to save a single entity at a time with entityManager.saveChanges([childA]) as they are ready. Just pass in an array with a single entity that you want to save. This may be useful if you are working on multiple entities but they aren't all ready for saving and you need to navigate around your app. Unless you call cancelChanges() Breeze will just keep the entity in cache until you are ready to use it again. In this manner, just make a call for entities in the isAdded() state and you can pull 'em back in and edit again.

Reject Changes Does Not Remove Entity From Parent

When I create a new entity and set its navigation property and then reject the changes the parent holds onto a blank entity. Do I need to explicitly remove the new entity from the parent before rejecting changes? I did not explicitly add it to the parent I just set the new entity's parent id.
Rejecting changes on a new entity simply discards the entity - making its entityState 'detached'. Any children that were attached to the parent effectively get stranded in this case, i.e. they have no parent.
In other words, Breeze does NOT call rejectChanges on any children as a result of a rejectChanges on a parent. This is deliberate.
So your best bet is to call rejectChanges on the children as well. If they were new entities themselves they will also become detached, otherwise their parents will revert to whichever entity was their previous parent.
Note that you can use the EntityManager.getEntities method to return all of the entities of specified entityTypes and entityStates. This can be useful in determining which entities you want to 'roll back'.
See the Entity Manager getEntities method

Resources