I am having difficulty figuring out if and or how I can search child objects as well as their parents using NSPredicate(or some other method). For instance, I have a Wine Object that has properties like name, vineyard, region and year. Then I have a child object like "Event" which has properties like WhoSharedWith, FoodAteWith, EventDate, etc. I can figure out a Predicate for the Wine Object but what if the person types in "Steak"? I want to search the "Event" objects UNDER the wine objects to see which Wines are good with Steak. Can anybody help me out?
thanks
In Core Data terminology, you have multiple Entities (Event, Wine) connected by a relationship. There is no notion of parent and child Entities (unless you are creating subentities, akin to subclassing, which it appears you are not doing).
All of the Entities are peers. You can start anywhere in your object graph and follow the relationships to get to any related objects. You can use the relationships' keypaths in your predicate. See the Predicate Programming Guide.
Related
In a demo project I am setting up as a proof of concept I am finding myself with a lot of duplicated DTOs and fields. For instance considering 1 root object representing an item or inventory, I would have the following classes and properties
CreateItem [ Code, Description, Weight ]
Entity on aggregate root [ Code, Description, Weight ]
ItemCreated event [ Code, Description, Weight ]
Item read model [ Code, Description, Weight ]
Query request object [ Code, Description, Weight, Page, PageSize ]
Response DTO [ Code, Description, Weight ]
and so on
All these objects are a result of separating my app into the traditional Domain, Application, Presentation layers.
How are you managing all this duplication? Tools like AutoMapper and such help to convert between them, but if I wanted to add a new property to Item that would be used everywhere I would have to update all these models.
Because the domain model may not be exactly the same as the application read model, I understand the need for separate definitions, however this can very quickly become a maintenance nightmare.
Charles,
An approach that might help you get rid of some bits of duplication could be the following:
do not add public properties on the entity. As you are using event sourcing, the internal state of the entity will be restored by replaying the events associated with the entity in question. And nobody from outside the entity should know how the reconstructed state of the entity is represented - a series of private fields, an array of string objects, whatever. After all, you can choose to have no internal representation of its state, but implement all the behavior (all the methods) by simply replaying the events each and every time :) So, at one extreme, you may have 1 single field on the entity = a collection of events.
Item read model and Response DTO... Make them the same thing! As you are using cqrs, that is, you have already segregated the read model from the write model, there is no need to make a lasagna out of the read-side of the application. It is OK to have a minimum number of abstraction layers on the read-side. The read model is already behavior-less, it is data only. It's a DTO that gets constructed from events, gets persisted into a data storage with a (more or less) denormalized schema and, upon user request, is retrieved from the storage and presented on the UI or so. It's pure data that gets transferred from one place to another. Though, if, for some reason, you have to return to the end user (human or machine) some other data in addition to the data from the read model object, apply basic object composition. Compose two or more behavior-less objects into one such object. And send the latter on the wire.
speaking of composition, you may even define a (value) type such as ItemDescriptor [Code, Description, Weight] in a shared library and use it when defining the CreateItem command, the ItemCreated event, the read model, the query request object or so. If you are using a language that supports mixins, then mix that ItemDescriptor in :) Else, basic composition may be applied.
Furthermore, the "maintenance nightmare" can be ameliorated to some extent if packaging by feature would be used instead of packaging by layer.
Also, perhaps this post might help a bit.
I am quite familiar with dealing with simple entity relationships, such as making a group that contains a collection of many items. However, I'm wondering how to achieve a particular relationship within my data structure.
Currently my data structure is made of entity Group and entity Item which has a one-to-many relationship from Group. The item exists only in a single group. However, it can also provide a link to another group as required.
So an analogy for the situation could be: Group = House, Item = Inhabitants. I live at a particular house, but I can also provide information about where to find other houses.
Another analogy could be: Group = Playlist, Item = Songs. I listen to the songs of the playlist, then when I get to a particular song I can (optionally) decide to switch to another playlist.
Now I am pretty sure this is not the way to achieve this behaviour. I had the notion that it should be an attribute rather than a relationship, but I don't know if there is a way to link attributes unrelated NSManagedObjects (that I know of).
I'm thinking that it's not impossible, just that it requires a little more understanding of databases to achieve. Any advice, tutorials would be greatly appreciated!
EDIT: This is my second attempt at the data structure. Instead of it being a relationship, I've made a integer identifier on the group, and particular items can store this identifier as necessary in the form of an attribute.
The otherGroupIdentifier would store a value equal to identifier on the Group entity. That way I can link through to it as explained previously. However, this certainly does not seem to be the cleanest way to implement Core Data. Maybe what I am looking for is not possible or too complex for a Core Data system?
I'm able to work with objects on a context and work with relationships. My registered objects are behaving correctly.
My store is added to the coordinator with the correct configuration (the configuration having 3 entities, one entity with the two other entities having a to-many relationship to the first entity).
Saving the store with either -many entity or with both -many entities works correctly. However, when I add the one- entity to the context, the object graph will not save.
It seems like it would be a common beginner's problem, but that means its also a difficult solution for beginners. I expect I'm not the first one to have run into this kind of trouble?
UPDATE: Thank you for the replies and pointers. It seems the main trouble is as subtly pointed out, that I am not handling errors properly. After looking at this post, Core Data Entity Relationship Does Not Save Between Launches , I have started improving with error handling. The localized description on this issue was 'ID required'. While I still don't know what that means, I can at least have the chance to figure it out, now.
To-Many relationships are represented as sets on the object. So child ->> parent implies that child.parent is represented as a set. Therefore, when you add a new parent object, you need to add that parent object to the set before you save the context. If you say self.parent = inserted_parent_object, I am not sure what would happen. If you are going the other way around it is easier. When you insert the parent object, just set the child (assuming you have it) and save the context. That will work unless it is a many to many relationship.
If there is an error, the code and the error message would be helpful in order to help you debug.
This one has code:
CoreData adding relationships to-many
I´m a little confused about inheritance and relationships in core data, and I was hopping someone could drive to the right path. In my app i have created 3 entities, and none of them have (and are not suppose to have) common properties, but there´s gonna be a save and a load button for all the work that the user does. From my understanding I need to "wrap" all the entities "work" into an object which will be used to save and load, and my question is, do I need to create relationships between the entities? Because I have to relate them somehow and this is what make sense to me. Is my logic correct?
I'm implementing a budget calculator, and for the purpose of everyone understand what my issue is, I´m going to give an practical example and please correct me if my logic is incorrect:
Let´s just say you are a fruit seller, and because of that it´s normal to have a database of clients and also a fruit database with the kinds of fruit you sell. From my understanding I find two entities here:
Client with properties named: name, address, phone, email, etc.
Stock with properties named: name, weight, stock, cost, supplier, etc.
TheBudget with properties named: name, amount, type, cost, delivery, etc.
I didn´t put all the properties because I think you get the point. I mean as you can see, there´s only two properties I could inherit; the rest is different. So, if I was doing a budget for a client, I can have as many clients I want and also the amount of stock, but what about the actual budget?
I´m sorry if my explanation was not very clear, but if it was..what kind of relationships should I be creating? I think Client and TheBudget have a connection. What do you advise me?
That's not entirely correct, but some parts are on the right track. I've broken your question down into three parts: relationships, inheritance and the Managed Object Context to hopefully help you understand each part separately:
Relationships
Relationships are usually used to indicate that one entity can 'belong' to another (i.e. an employee can belong to a company). You can setup multiple one-to-many relationships (i.e. an employee belongs to a company and a boss) and you can setup the inverse relationships (which is better described with the word 'owns' or 'has', such as 'one company has many employees).
There are many even more complicated relationships depending on your needs and a whole set of delete rules that you can tell the system to follow when an entity in a relationship is deleted. When first starting out I found it easiest to stick with one-to-one and one-to-many relationships like I've described above.
Inheritance
Inheritance is best described as a sort of base template that is used for other, more specific entities. You are correct in stating that you could use inheritance as a sort of protocol to define some basic attributes that are common across a number of entities. A good example of this would be having a base class 'Employee' with attributes 'name', 'address' and 'start date'. You could then create other entities that inherit from this Employee entity, such as 'Marketing Rep', 'HR', 'Sales Rep', etc. which all have the common attributes 'name', 'address' and 'start date' without creating those attributes on each individual entity. Then, if you wanted to update your model and add, delete or modify a common attribute, you could do so on the parent entity and all of its children will inherit those changes automatically.
Managed Object Context (i.e. saving)
Now, onto the other part of your question/statement: wrapping all of your entities into an object which will be used to save and load. You do not need to create this object, core data uses the NSManagedObjectContext (MOC for short) specifically for this purpose. The MOC is tasked with keeping track of objects you create, delete and modify. In order to save your changes, you simply call the save: method on your MOC.
If you post your entities and what they do, I might be able to help make suggestions on ways to set it up in core data. You want to do your best to setup as robust a core data model as you can during the initial development process. The OS needs to be able to 'upgrade' the backing store to incorporate any changes you've made between your core data model revisions. If you do a poor job of setting up your core data model initially and release your code that way, it can be very difficult to try and make a complicated model update when the app is in the wild (as you've probably guessed, this is advice born out of painful experience :)
I've got a simple pojo named "Parent" which contains a collection of object "Child".
In hibernate/jpa, it's simply a one-to-many association, children do not know their parent: these Child objects can have different type of Parent so it easier to not know the parent (think of Child which represents Tags and parents can be different object types which have tags).
Now, I send my Parent object to the client view of my web site to allow user to modify it.
For it, I use Hibernate/GWT/Gilead.
My user mades some changes and click the save button (ajax) which sends my Parent object to the server. fields of my parent has been modified but more important, some Child objects has been added or deleted in the collection.
To summary, when Parent object comes back to server, it now has in its collection:
- new "Child" objects where id is null and need to be persist
- modified "Child" objects where id is not null and need to be merge
- potentially hacked "Child" objects where id is not null but are not originally owned by the Parent
- Child objects missing (deleted): need to be deleted
How do you save the parent object (and its collection) ? do you load the parent collection from database to compare each objects of the modified collection to see if there is no hacked item ?
Do you clear the old collection (to remove orphan) and re add new child (but there is some Child that has not been modified) ?
thanks
PS: sorry for my english, I hope you have understand the concept ;)
Something in your stack has to supply the logic you are talking about, and given your circumstances it is probably you. You will have to get the current persisted state of the object by reading from your datasource so you can do the comparison. Bear in mind that, if several legitimate actions can update your parent object and its collection simultaneously you will have to take great care over defining your transaction grain and the thread-safe nature of your code.
This is not a simple problem by any means and there may well be framework features that can assist, but I am yet to find something which has solved this for any real world implementation I have encountered, especially where I have logic which tried to distinguish between legitimate and "hacked" data.
You may consider altering your architecture such that the parent and children are persisted in separate actions. It may not be appropriate in your case but you might be able to have a finer grain of transaction by splitting up the persistence actions and provide child-oriented security which makes your problem of hacking a little more manageable.
Good luck. I recommend you draw a detailed flow chart of your logic before you do too much coding.
The best solution I've found is to manage a DTO, manually created. The DTO sends only needed datas to the client. For each fields I want to set in ReadOnly mode, I calculate a signature based on a secret key that I send to client with my dto.
When my DTO comes back to server, I check the signature to be sure that my read only fields have not changed (recalculate the signature with coming back fields and compare it to the signature coming back with dto)
It allows me to specify read only fields and be sure that my objects are not hacked.