What's the point of a fetched property? Does someone have a good example what this is good for?
Some of the uses for fetched properties:
Ordered relationships. The Core Data to-many relationship models a (unordered) set. You can provide the appearance of an ordered relationship using a fetched property with a sort descriptor (assuming there's a natural ordering to the elements).
Cross-store relationships. Relationships in Core Data cannot span persistent stores. You can simulate such relationships using fetched properties, for example storing the objectIDs of the destination in a transformable property and fetching the elements of that collection of objectIDs. Obviously true cross-store relationships are problematic because there's no way to guarantee the presence of an other store at access time.
Filtered relationships. Although fetched properties are not "live' (like iTunes' smart playlists), they can be used to easily filter members of one or more relationships according to attributes (persistent or transient) of any object in the connected object graph.
Related
I'm trying to get my head around NoSQL and Google Cloud Datastore, and I don't know how to chose between two different options for storing data.
I have a list of orders, and every order is for an unspecified number of products. What are the pros/cons of storing the product list as an array property for the order entity vs having product child entities for each order parent?
Firstly, be well aware of the distinction between the 2 possible approaches of implementing a relationship between entities:
one entity can contain a Key type property pointing to another entity (which might or might not exist!) - this is a functional relationship only, not one at the datastore level
having the 2 datastore entities in a parent-child (ancestry) relationship, inside the same datastore entity group.
Using the 2nd one has scalability implications, see also:
Ancestor relation in datastore
E-commerce Product Categories in Google App Engine (Python)
As for storing a list as an array property vs as separate entities, see Creating your own activity logging in GAE/P (where repeated properties is just how array properties are called in the ndb client library context).
I am facing same problem as here
How to achieve relationships between entity in one store with other?
Kindly guide me through this.
It is indeed possible and makes total sense in some cases to split objects across stores
lets assume obj A in Store #1 and obj B in Store #2.
Each A has N Bs
easiest solution would maybe be a TRANSIENT property on A ... named 'allMyBs'
then implement the fetch in code:
- (NSArray*)allMyBs {
NSFetchRequest *r == ... //setup to fetch Entity B
[CoreDataHelper managedObjectContextForStore2] executeFetchRequest:r];
}
this isnt the fetched property yet but easy
see Cross-Store weak relationship with Fetched Properties? for a complicated way ^^
The short answer is that you can't. You can't have a relationship between managed objects that crosses persistent stores.
You can, however, implement a key or identifier in your model that YOU maintain across stores, and use that find 'related' objects in different stores.
If you have user records in one store, and application data in another, the application records might have a "belongsTo" property whose value is a user ID corresponding to a user record in the user store.
Apple's documentation is very specific about this:
From the Core Data Programming Guide:
"Core Data does not let you create relationships that cross stores. If you need to create a relationship from objects in one store to objects in another, you should consider using fetched properties."
Again, from the Core Data Programming Guide:
"You must be careful not to create relationships from instances in one persistent store to instances in another persistent store, as this is not supported by Core Data. If you need to create a relationship between entities in different stores, you typically use fetched properties (see “Fetched Properties”)."
This is exactly what I am talking about above. If you implement fetched properties that way, it is up to you to maintain the integrity of the graph. The same document walks you through creating and using fetched properties. Perhaps you can be more specific in what you need answered.
My iPhone app has a summary page (UITableView) where I would like to show a quick overview and therefore I need to get info from several entities. It was suggested to create an abstract parent entity and have my two entities as children of this one. This do allow me to fetch the two entities using the one fetchedresultscontroller.
This works but I find that I need to filter the return a small bit. Because of the 'hack' above these entities have nothing in common so I need completely separate predicates.so from EntityA I would need "color = blue" and from EntityB "length >= 10". Because the entity I'm actually querying have none of these this doesn't work at all.
Is there a way to do this or what's the best approach here?
Niether the UITableView or the NSFetchedResultsController is designed to deal with more than one entity at a time. Moreover, it seldom makes any sense to try to do so. If you find yourself in such a situation, you probably need to rethink your data model design.
If entities are logically associated with each other then they should be linked by a relationship. If data from any two objects is to be displayed in the same tableviewCell without being gibberish then they must have some logical association and therefore should be linked by a relationship of some kind. To display in the table, you fetch one side of the relationship and then walk the relationship/s to find the other related objects.
If the logical association is strong, it should be defined as a formal relationship in the data model e.g.:
EntityA{
//... some attributes
b<-->B.a
}
EntityB{
//...some attributes
a<-->A.b
}
However, if the relationship is weak or transient, then you should use a fetched property to relate them. The fetched property dynamically searches for other entities based on a preprogrammed fetch.
EntityA{
creationDate:date
someBs--(creationDate=$FETCH_SOURCE.creationDate)-->B
}
EntityB{
creationDate:date
}
A key concept here is that Core Data is providing the entire model layer of your Model-View-Controller design. It is not just a dumb database but an active object graph that models both the data itself and its behavior. Once you have a properly designed data model, problems with the controllers and views resolve themselves automatically.
If i understand correctly, you can use notifications and send a dictionary of required information to the UITableView view controller class.
I have a Core Data object called Car that has a one-to-many relationship with another Core Data object called Claims (i.e., one Car has many Claims). I've created the entities in the data model editor, and am able to list, edit, and work with the Car objects.
What I can't figure out is this: given a Car, how to get an array of all related Claim objects. I think it requires a fetch request, but how does it work?
Thanks!
If the entities are related, you'll want to add a relationship to your models. In core data relationships are two-way, so Car would have a to-many relationship called "claims" and Claim would have a to-one relationship called "car".
Having these relationships in place will give an instance of Car an NSSet of claim objects.
I have two entities that are connected through a one-to-many relationship, let's say CategoryEntity and ItemEntity. The relationship is optional for CategoryEntity (there can be categories without items), but required for every ItemEntity. At the app's loading, the Categories already exist in the store, and I want to import ItemEntities and connect them to the appropriate CategoryEntity.
Obviously executing a FetchRequest for each ItemEntity to find the matching category wouldn't be a good solution because there will be about 4000-6000 Items each time..
So, is there something more efficient I could do?
If you have correctly setup your Core Data model, then you have a to-many relationship from the Category entity to the Item entity, and an inverse to-one relationship from Item to Category. Also, you have a "cascade" delete rule for the to-many relationship and a "nullify" delete rule for the to-one relationship.
Assuming this, each time you insert an Item object, setting its Category relationship automatically inserts the Item into the corresponding Category. Deleting an Item automatically removes it from the corresponding Category.
On the Category side, removing a Category automatically removes all of the corresponding Item objects.
Therefore, when you fetch Items, you have already fetched for each Item object its corresponding Category object. You do not need do anything else. Note that, by default, you are not actually retrieving the Category object during the fetch: instead a fault is fired the first time you try to access the object and the object is retrieved at that time. This provides better performances if you do not plan to use immediately the Category object stored within the Item object just fetched. If you plan to use the Category object almost every time you fetch an Item, then you must use the NSFetchRequest methods
- (void)setReturnsObjectsAsFaults:(BOOL)yesNo
- (void)setRelationshipKeyPathsForPrefetching:(NSArray *)keys
to tell Core Data that you do now want faults and that you ask for prefetching your Category relationship.
When you say 'import' item entities, what do you mean? Are these in another Core Data store, defined in another format in a file somewhere, retrieved over the network?
One approach would be to fetch all the categories in one go and add them to an NSDictionary acting as a cache and keyed by some identifying value that allows you to perform a quick lookup. For each item entity that you instantiate during import (whatever that means), retrieve its category ID and then retrieve the Category MO from the cache. Set the relationship and then save. Even better, batch up a number of insertions and save every 10, 100 or 1000 to reduce IO overhead.