I have two managedObjectContexts(MOC): a temporaryMOC and a persistedMOC. If I initialize an entity in the tempMOC and the user decides to save, I save and merge the changes into the persistedMOC and save. In which MOC are now those entities? If the user start a new file, there will be now two entities in the tempMOC?
The MOCs is only a scratchpad with which you can create, update, delete and retrieve NSManagedObjects.
If you've got two objects as a result of a save operation - it means you've mistakenly created two entities that are saved with the merge.
Could you show us the code in which you create an object?
Related
I am working on to use CoreData to save data of an object to an entity created in the datamodeld file.
In my scenario, I made a datamodeld called Product which represents an item available in the grocery store.
I have several categories for each type of products. For example, produce, dairy, meat, etc... If I save those products in the Product context, they will all be aggregated into one database and retrieving the data will be a hassle.
I'm wondering if it is possible to store my items into different databases of the Product context.
The only workaround I can think of is to create an entity for each categories which is a child of Product. I don't like this workaround because I am creating unnecessarily entities (every products in each categories have the same attributes).
By "product context", I guess you mean managedObjextContext? Your data is not saved in moc, you write data on moc and it's reflected persistent store.
You can use multiple moc to save the data of your app but be extra careful to syncronize the moc to moc on main thread.
I did something on the same lines that you are proposing as a work around. It worked out fine in my case.
I found a question very similar to mine here, but it was un-replied to and unanswered so I will try again.
I may be missing something in regards to cascade deletes and core data. I am used to cascade deletes working as designed in RDBMS apps but having issues with core data.
I have an object record that get's inserted into entity via an "add form" called modally from a table view. No problem.
In another session I will insert objects into a related details entity (many) where there is a common loadID attribute in both. No problem.
In another session, I will call up the original table view to view the parent "loads", and swipe-delete, save the context, and the parent load gets deleted from the one side entity. No problem, (except apparently details objects in a many side entity do not get removed)
When I open the sqlite data source with a db manager, I see the child records (pay detail items) are being orphaned. I have double and triple checked the cascade delete settings in the relationships. Have tried different entity relationship settings combinations, but nothing seems to get the many records to automatically delete along with the parent record.
If you can't define corresponding keys in core data, how does core data know what belongs to what when you operate in multiple sessions (contexts) adding child objects to the many-side entity?
I don't know if I'm doing something wrong or missing a vital step prior to inserting new child objects in the many table, or doing something wrong or missing a step when deleting the parent object.
But I would suggest all with cascade deletes set to open your data file and be sure there are not orphaned objects (records)
I have two persistent stores with objects that use the same model. I would like to open both stores in one context, but save the context to only a single store, and then safely delete one of the stores. I am in essence trying to merge the contents of two persistent stores into a single persistent store. Because the entities have relationships, I am finding this difficult.
From this answer:
If you do need to have relationships between the objects in both stores, or you really just want to have a single store, your best bet would be to create a second NSPersistentStoreCoordinator and a third, distinct persistent store to hold the merged object graph. You will need to write code to create copies of the objects in a managed object context attached to this second NSPersistentStoreCoordinator. You'll need to set up the same relationships among the copies that the original objects had, too, but how you go about doing this depends on your data model.
That makes it seem clear, except for the details of how, literally, to make copies of the objects for the new store. Is this a migration issue?
Ultimately, I used the following approach:
[migrator migrateStoreFromURL:[NSURL fileURLWithPath:incomingPath]
type:nil
options:nil
withMappingModel:managedObjectModel
toDestinationURL:[NSURL fileURLWithPath:finalPath]
destinationType:nil
destinationOptions:nil
error:&err];
[persistentStoreCoordinator removePersistentStore:[[persistentStoreCoordinator persistentStores]lastObject] error:&err];
The file at "incomingPath" was the store I imported, the file at "finalPath" the already-existent store that I wanted to merge into. Both stores were open in the same persistent coordinator, and both use the same object model. I then removed the incoming store and never looked at it again; I suppose I could have deleted it at the file system level.
For my particular data needs, I then fetched all the records, culled out the duplicates, and saved the context.
I publish this answer because as a core data newbie this simple migration solved the "can't save relationships to objects in different stores" problem non-intuitively.
I am trying to add an entity to the DB. Once I have added it, I want to detach it, so I can manipulate the object safely without making any changes to the DB. After calling context.SaveChanges() I do the following to detach the entity:
// save
context.Stories.Add(story);
// attach tags. They already exists in the database
foreach(var tag in story.Tags)
context.Entry(tag).State = System.Data.EntityState.Unchanged;
context.SaveChanges();
context.Entry(story).State = System.Data.EntityState.Detached;
However, changing the entity state to DETACHED will remove all related entities associated with the my entity. Is there a way to stop this ?
If I don't detach the entity, all my changes are sent to the DB next time I call context.SaveChanges()
Thanks!!
There is no way. It is limitation of EF. Your options are:
Not using the same context for another save (single context instance = single save)
Retrieve the entity from database again using another context instance which will not be used for saving
Create deep clone of your entity and use the clonned one (deep clone is done by serialization and immediate deserialization = your entity graph must be serializable)
I think there are two ways to approach this problem:
Purist: retrieving entities from a DbContext and modifying them without saving is a misuse of the tools and the architecture. Use a DTO instead.
Pragmatic: you can use AsNoTracking() to retrieve an entity graph that will not be tracked by the context for changes.
This is a bit of a tricky one.
I have Document entities that are currently being imported into CoreData from a SQLite database on a background thread. There's a separate context for the background thread and I am batching the save at every 500 entries.
Saving the background thread context triggers a notification which grabs my main thread's contexts and performs a merge between the two.
Everything works as expected if I am only importing document entities.
My problem occurs when I try and establish a relationship between the current document being created, an another entity called briefcase.
This is what my import routine currently does:
Create Briefcase entity
Loops through SQLite database rows and creates Document entities for each row
Create the relationship between the document in the loop and the briefcase entity
At every 500 rows, I save & reset the context. This triggers a ContextSave notification which grabs the main thread and merges with the main thread's context.
This is where my issue is: after the save & reset above, my Briefcase entity gets merged with the main thread so when my loop continues, the next document entity created tries to associate itself with the briefcase, which is where I get a crash saying I can't establish relationships between objects on separate threads.
I know that if I remove the call to reset the context after saving it, everything works as expected but my memory footprint goes way up and it is not something I am prepared to accept.
So my question is:
Can you think of a way of keeping the Briefcase entity around (and valid) for the entire import process so I can continue to create the relationships?
My first thought was to create the briefcase entity without a context and then add it to the context once the whole process is finished. This didn't work very well (it crashed on creation).
Your thoughts are very much appreciated.
Rog
Answering my own question:
Create Briefcase entity
Loop through SQLite database rows and create Document entities for each row
Create the relationship between the document in the loop and the briefcase entity
At every 500 rows, save context & immediately store the objectID for Briefcase after saving
Now it's ok to reset the context
(Re)retrieve the briefcase instance using the objectID saved above and the existingObjectWithID:error: method
Loop continues...