Breeze: Specifying order of entity initialization - breeze

Through a breeze query we are fetching a set of entities.
The entity graph looks similar to this:
EntityA {id, prop1:EntityB}
EntityB {id, prop1:EntityC}
EntityC {id}
On the client-side, for each entity we have an Initializer method passed to metadataStore.registerEntityTypeCtor.
In the Initializer of EnitityA, we do this:
if (EntityA.EntityB.EntityC){
//do things
}
We have noticed that, depending on the order in which properties are defined on the server-side model, EntityC is not yet initialized when this code is reached.
If on the server-side model, we defined the property of type EntityC before the property of type EntityB, then EntityC will be initialized when the above code is reached.
Is there a way to specifiy on the client-side which order entities should be initialized, without relying on the order they are defined server-side ?

Related

Is the order of the entities returned from `Repository#save([array])` guaranteed?

In TypeORM, if we have a repository called repo, we can call repo.save([entity1, entity2]) to save new entities and/or update existing ones. Repository#save also returns an array of the saved entities.
Is the order of the returned entities guaranteed to match the order that was passed in?
For example, if I call repo.save([newEntity1, newEntity2, newEntity3]) (where each is a new entity without an ID), will I always get back [entity1, entity2, entity3], where each element in the output array corresponds to the respective element in the input array, but with an assigned ID?
In my testing, the order seems to match, but I want to be sure that it's guaranteed.
Repository documentation: https://typeorm.io/#/repository-api
Relevant passage:
save - Saves a given entity or array of entities. If the entity already exist in the database, it is updated. If the entity does not exist in the database, it is inserted. It saves all given entities in a single transaction (in the case of entity, manager is not transactional). Also supports partial updating since all undefined properties are skipped. Returns the saved entity/entities.
It's not clear what guarantees this provides about the order.

NSManagedObject entity class method

I recently realized that NSManagedObject subclasses inherit a class method entity which can be used to obtain a NSEntityDescription for the class. However, I was used to having to specify a context when creating a NSEntityDescription, as with entityForName:inManagedObjectContext:. Is it ok to use the simpler entity method and what context will it be associated with ?
This method is not really documented by Apple.
An NSEntityDescription is not part of a managed object context-- it's part of the managed object model.
When you load a data model, all of the entity descriptions it contains are loaded. The class method +entity works because the entity description was created along with the model object. If you try to call this method before loading the model, it returns nil in Objective-C. (In Swift for some reason it returns a non-optional value, so it's not nil, but if you use it your app will crash. Don't ask me why it's like this.)
You can also use +entityForName:inManagedObjectContext:, as you mentioned. But look at the documentation for that method:
Returns the entity with the specified name from the managed object model associated with the specified managed object context’s persistent store coordinator.
So even though the method takes a managed object context argument, it's still using the managed object model. It's using the context to find the model. The object that you get isn't associated with the context, it's associated with the underlying data model.
These two methods are equally safe. Use whichever works best in your code.

Correct method for adding master/child entity in 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);

Core data parent entity generated NSManagedObject subclass

I have in my model a parent entity, "List" and a child entity (subentity) named "UserList" which is just a type of list. "UserList" has no attributes or relationships of its own, it inherits everything from List. List has a to-many relationship to ListItem.
I ask XCode 4.2 to generate the NSManagedObject subclasses.
For List it generates what I'd expect including,
- (void)insertObject:(NSManagedObject *)value inListItemsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromListItemsAtIndex:(NSUInteger)idx;
...
However the generated "UserList" class does not declare any methods which would be ok if it was declared as a subclass of "List" but thats not what it generated.
#interface UserList : NSManagedObject
#end
Is UserList really a subclass of List? Can I just change the header? Or is something more complex going on?
A couple of things to check. First, make sure you have given both List and UserList entities a class name, and then make sure UserList has declared List as its parent entity.
The generator is finicky. If you have not specifically assigned a class name in the model GUI, it generates them on the fly. Unfortunately, it means that, depending on the order in which they are generated, some may not be generated with the right information (imaging UserList being generated first... if you did not specifically give List a class name, it only knows to use NSManagedObject).
By convention, I always specifically assign class names in the model GUI. I've not seen this happen when I specifically assign a class to each entity (under where you give the entity its name), but I guess it may happen.
Try to re-generate the class files. It may just get generated correctly this time.
EDIT
Clarification after comment...
NOTE: Unfortunately, Xcode is being very consistent in this matter. If you do not explicitly give class names to entities, others that reference it will be generated with "wrong" class names.
I suggest following one of following options for your work flow.
Always assign class names in the GUI for each entity.
Always generate the classes twice when you generate for the first time.
Use mogenerator https://github.com/rentzsch/mogenerator#readme instead of the Xcode class generator.

EF Code First NotMapped Attribute?

I have properties on my POCOs like the following that allow me to easily access identifying criteria that a user will be able to associate an entity record with for use in my auditing and validation code...
Sometime the Identifer is a simple concatenation of 2 or more scalar fields, and sometimes it has code in it to retrieve and concatenate properties on a Navigation Reference.
I don't need to store this data with each entity in the DB, BUT I do want to be able to access it thru the DbEntityEntry, I tried decorating it with [NotMapped] but then it is not accessible on my entity ?
[Identifer]
public string Identifer
{
get { return HRContact.Identifer; }
set { }
}
Anyone know how to accomplish this ?
Thanks
Greg
I'm not sure what you mean be accessing those data through DbEntityEntry. DbEntityEntry contains reference to entity in Entity property - there you will get access to any properties the entity provides. DbEntityEntry also holds collection of current values and original values. These collections will always contain only mapped (persisted) properties because EF never deals with not mapped properties.

Resources