Many-to-many relationship constrains in Core Data - iphone

I have entities Word and Tag. Both have To-Many relationship to each other, as well as inverse. The way I need to constrain it that:
if I delete a Word then only the related Tags which has no Word pointing to them will be deleted
if I delete a Tag which has Words pointing to it then just nullify those set items.
Is it possible to model?

This is something that needs to be handled in code. You need to create custom subclasses for your Word and Tag entities and implement the -prepareForDeletion method in each. Then you can check the logic and handle it appropriately. I would also set the delete rule for the relationships between the entities as deny

Related

Proper way to generate a view from a many to many relationship?

I have two tables - ContactInformation & EmailAddress - which have a many to many (* : *) relationship. After making this association in the ADO.NET data model and generate the db from it, a table titled ContactInformationEmailAddresses which maps the two tables is created in the Entities Container.
Unlike when I scaffold views which have a 1:* relationship, there's no entries available for its counterpart in the view when I scaffold either one and scaffolding off the combined table isn't an option even after updating the model from the db.
My question is simply: is there an automated way to generate the creation form for ContactInformationEmailAddresses that will have the EmailAddress entry field?
At present the scaffolding templates don’t support generating views that require the selection and association with more than one entity – the “many” end of the association.
Make sure to check out this blog article
http://blogs.msdn.com/b/mcsuksoldev/archive/2013/09/20/managing-entity-relationships-with-mvc-scaffolding.aspx

Modeling a to-many relationship in Core Data

I asked this question earlier, but I'm missing one important thing. I have a NoteObject entity and every note, without Core Data, just has an arrayOfTags (which is an array of NSStrings). I decided to use to-many relationships to store the tags instead of an array. So I created a new "Tags" entity, and set up a to-many relationship from my NoteObject to Tags. This works great when every tag is related to only one note, but I'm unsure how I would go about linking one tag with multiple notes. How would I set up that relationship?
In you data modeler just make the Tags -> Notes relationship a to-many relationship. If you have already generated the Entity subclasses you will have to redo those. You will also have to be careful when creating tags to ensure uniqueness, but other than that it should be fairly straightforward. myTag.notes should work just as well as myNote.tags.

Coredata delete rule confusion, xcode

I have a Core Data relationship between two entities, which is like this:
Entity A Entity B
aRelationship <-------------->> bRelationship
With the delete rule set to cascade.
Maybe I have this wrong, but I thought that if the delete rule for both of these relationships was set to "Cascade", then when did the following...
[context deleteObject:EntityA];
...it would also delete all the of the Entity B's associated with it. However when I log all of my entity B's it would seem that I am mistaken.
Could someone please shed some light on my confusion?
Thank you very much.
While it's not immediately apparent in the graphical data model editor each recipocal relationship i.e. each
<-->
...is really two separate relationship each with its own delete rule. Delete rules are activate when an object of the entity with the delete rule is deleted.
So, if in the data model editor you have two entities Alpha and Beta with a relationship:
Alpha.betas<-->>Beta.alpha
… then you really have two relationships like so:
Alpha.betas--(delete rule)-->>Beta.alpha
Beta.alpha--(delete rule)-->Alpha.betas
You never want to set up a delete rule like this:
Alpha.betas--(cascade)-->>Beta.alpha
Beta.alpha--(cascade)-->Alpha.betas
… because deleting any one Beta instance will delete the associate Alpha object which will trigger the deletion of all related Beta objects. Depending on the details of your data model, a reciprocal cascade can delete a big chunk of you data by accident.
What you really want is:
Alpha.betas--(cascade)-->>Beta.alpha
Beta.alpha--(nullify)-->Alpha.betas
Now, when you delete the Alpha object, it will delete all associated Beta objects.
When a cascade is blocked, it is usually a problem with a required relationship. Can't tell for certain without details of the data model.
It depends on what delete rules are you using.
Here is what Apple said in their document:
"When you delete a managed object it is important to consider its
relationships and in particular the delete rules specified for the
relationships. If all of a managed object's relationship delete rules
are Nullify, then for that object at least there is no additional work
to do (you may have to consider other objects that were at the
destination of the relationship—if the inverse relationship was either
mandatory or had a lower limit on cardinality, then the destination
object or objects might be in an invalid state). If a relationship
delete rule is Cascade, then deleting one object may result in the
deletion of others. If a rule is Deny, then before you delete an
object you must remove the destination object or objects from the
relationship, otherwise you will get a validation error when you save.
If a delete rule is No Action, then you must ensure that you take
whatever steps are necessary to ensure the integrity of the object
graph."
The link of “Relationship Delete Rules.”: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW1

how can i know when a self-tracking entity has been changed?

I have been working with the Entity Framework + Self-Tracking entities, and came out with a problem:
Is there any way to determine when an entity has been changed??
For example: If you have an entity User with two fields: Name and Password, you can know if an User instance has been changed making:
<user>.ChangeTracker.State != ObjectState.Unchanged;
My problem is when the User has a Person, and the person has a field Email. I want that if the email field is changed, then the corresponding User is changed too.
I have been trying with methods such as: <user>.StartTrackingAll(); but this does not work with navigation properties (or maybe i am doing something wrong). Some help about this can be found here.
Remember that the Self tracking entities are autogenerated via T4 templates, so the clases can't be modified.
First when wanting to know if any entity in a so-called object graph has changed you can recurse through all entities contained in trackable collections or one-to-one navigation properties of a root entity (user in your case). This way you can know if a person inside the root entity has changed. This is actually how I check complex object graphs for any changes in any of the contained entities. But also for checking out if any of these entities have critical validation errors (so the user can't persist them yet).
Remember that the Self tracking entities are autogenerated via T4 templates, so the clases can't be modified.
Not true. First of all you can modify the T4 template to generate more (complex) code to achieve the things you want. And second, it generates partial classes which can easily be extended with custom (non-generated) code.
If you change the email in the Person instance only that instance is correctly marked as modified. That is absolutely correct behaviour. What do you expect? Do you expect that change to property in related entity will propagate changed state to relations? That would make STEs completely useless because any single change to entity graph would make all entities in the graph modified and each this modification causes additional roundtrip to the database.
If you want to set User as modified when you are changing email simply create some method or handle some event and call person.User.MarkAsModified()

fetchedresultscontroller with two entities - predicate to target each entity?

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.