Importing Large Dataset in Core Data - iphone

I'm trying to import large amout of data according to this solution. It is suggested that each importing threads should have its own managedObjectContext and they cannot pass any managedObject among them. So, my question is how we can set the relationship if two objects was created in different MOCs?
PS: After saving MOC in thread, it notifies the main MOC to merge the contexts. So related object for new object is always located in main MOC. In other words related object has already been created.

You can't pass NSManagedObjects between threads, but you can pass NSManagedObjectIDs.
Pass those over, and then retrieve the objects themselves from the context that you want to set the relationship within.

Related

Accessing managed object by objectID

I have three contexts:
masterMOC - private queue tied to the persistent store, so physical saves happen here
----mainMOC - main queue tied to the UI, child of masterMOC
-------backgroundMOC - private queue, child of mainMOC
Let's see I create an Employee object on the mainMOC, then save the mainMOC. Then I save the masterMOC (which writes to disk).
Now, I've saved the Employee NSManagedObjectID in a variable, objectID. I want to get this Employee on the backgroundMOC. Does [backgroundMOC objectWithId:objectID] serve this purpose? Will it go to the persistent store and fetch this object using that method? Or will I have to preform a fetch request?
Your'e doing it right. They want you to pass objects between MOContexts using ID's. objectWithId will hit the persistent store and load the object in a fresh state.
The only gotcha you have to worry about is this case.
You fetch an object or create a new object in a MOContext.
You try pass the objectID to another context WITHOUT SAVING
The new MOContext wont know about the updates, and if you created a new object the objectID wouldn't be in the persistent store, so I think it returns nil or it's not defined.
There is a WWDC video from this year titled 'Core Data Best Practices' that talks about nested MOC's. But to answer your question, yes, objectWithId will travel up through the fewest number of MOC levels to find the object. So if you call [backgroundMOC objectWithId:objectID] and the object exists in the mainMOC, it will get it from the mainMOC without having to go all the way to the masterMOC or the database.

Create a Core Date Entity Instance But not want it to be stored(non-persistent)

Sometimes I need instantiate CoreDateEntity to store some infomations for temporarily using.
But I needn't it be stored into DB.
currently I created a similar class which have same structures as the CoreDateEntity does.
It works well but I have to do many datas transfer between Two models.
Is there any better way to handle this?
Thanks for all the replies. but you guys just give me half answer of this. consider about this, I need place some entity without MOC into current database pool, how could I do this? I already checked the documents of CoreData, seems I didn't find API to transfer one entity from MOC to another MOC(manage object context).
According to Apple docs you can initialize a managed object without context if you specify nil as context.
- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context
You can assign entities to different stores when you set up the data model. Have one store be the persistent store and the other an in-memory store. You can't form relationships across stores but it sounds like you don't need that.
To assign a configuration, hit the configuration tab (the one with the wrench icon) in the entity detail (where you give it its name, class and parent). When you create the persistent store, add the configuration name to the options dictionary.
Update:
I think you maybe overcomplicating things. It sounds like you have some managed objects that will be temporary and some that will persisted but sometimes you may want to save the temporary objects. I don't think you should bother trying to separate out the "temporary" objects. Doing so just adds complexity without any performance benefit. Instead, just use ordinary persisted objects and then delete the ones you don't want.
Always try the simplest solution first.
Use two different managed object context's and only save the objects from one context. Be careful not to set relationships between objects of two different context's - this doesn't work.

Core Data performance deleteObject and save managed object context

I am trying to figure out the best way to bulk delete objects inside of my Core Data database.
I have some objects with a parent/child relationship. At times I need to "refresh" the parent object by clearing out all of the existing children objects and adding new ones to Core Data. The 'delete all' portion of this operation is where I am running into trouble.
I accomplish this by looping through the children and calling deleteObject for each one.
I have noticed that after the NSManagedObjectContext:Save call following all of the deleteObject calls is very slow when I am deleting 15,000 objects.
How can I speed up this call? Are there things happening during the save operation that I can be aware of and avoid by setting parameters different or setting up my model another way? I've noticed that memory spikes during this operation as well. I really just want to "delete * from".
Thanks.
Supposing that you have in your Core Data model a parent and a child entities, and the parent has a to-many relationship to child called children, you should be able to delete all of the child objects without looping as follows:
NSManagedObject *parentObject = ...;
[parentObject setValue:nil forKey:#"children"];
or using the Core Data generated method
- (void)removeChildren:(NSSet *)value;
NSSet *children = [parentObject valueForKey:#"children"];
[parentObject removeChildren:children];
I am not sure if this will speed up the NSManagedObjectContext save operation. Please let me know about the performances.
Check the relationship dependency graph: a cascade of deletes triggered by the initial deletion will slow things down. If those deletes are unnecessary then change the deletion rule.
according to apple website : http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdCreateMOs.html
it is very simple :
Deleting a managed object is straightforward. You simply send its managed object context a deleteObject: message, passing the object you want to delete as the argument.
[aContext deleteObject:aManagedObject];
This removes the managed object from the object graph. Just as a new object is not saved to the store until the context is saved, a deleted object is not removed from the store until the context is saved.

Core Data: Merging multiple Managed Object Contexts and deleting objects

I have an iPhone project where I have a series of Managed Objects in a Managed Object Context within the main application thread. On a separate thread, I import new objects from a webserver into a second Managed Object Context.
If the import goes ok without errors, I save the import context. This triggers contextDidSave from which I call mergeChangesFromContextDidSaveNotification. The two contexts merge ok. So far, so good.
My desired functionality is to have any objects that are in the original MOC but not in the imported MOC to be deleted (the idea is that the user is refreshing the data, and so old data should be deleted), but the merge seems to just combine the 2 MOCs.
Please can you advise if there is a way of managing the merge of the 2 MOCs so that those not in one are deleted in the other?
When you create the new moc it has access to all of the old objects so you can handle the deletion on the background thread as part of the import.
What you describe is not really just importing. The logic of deciding what objects are being "updated" is application specific. You can handle that on the import thread by fetching those objects and updating them rather than creating new instances or you can do the work after meting. Of the two options, I would prefer the first one as it's more inline with the Core Data way of things.
What I do in such situation, is a method "prepareForDelet" that marks a property "delete" to YES.
Then when I import my objects, if one exists already, I mark as delete NO.
When my thread is over, I can delete every objects whose delete is YES

Passing objects between managed object contexts

I have an iphone app with 2 managed object contexts. One of my contexts deals with a picker, which allows the user to add new records and then select one of those new records. Once the picker is hidden, that managed object context is saved and discarded.
I then want to use this selected object in my second managed object context, and add (relate) it to another object. This second MOC's changes may be saved or deleted. This is why the first MOC is created to allow the changes made in the picker to always be saved no matter wether they save or discard the changes in the second MOC.
I hope this is clear! My problem is that when the user selects the object from the picker, this object resides in a different context to where it needs to be used. Is there a way you can pass objects between contexts? Perhaps using the object's ID (after it has been persisted).
Thanks for your help!
You mentioned the correct solution in the question. You cannot pass NSManagedObjects between multiple contexts, but you can pass NSManagedObjectIDs and use them to query the appropriate context for the object represented by that ID. So simply persist out the data (via a save:), and then pass the ID to the other context and use it to ask the context for the appropriate object.
Depending on what you want to do you may want to rig up the mergeChangesFromContextDidSaveNotification: so that changes in one context are automatically reflected in the other.