Core Data Attribute dependent on Relationship - ios

I am trying to add an ordered array object to my CoreData setup, I know that you cannot do this as an NSSet is unordered, and I know that the simplest way to achieve this is to add an attribute to the entities within the set which can be used to order the set once you fetch it. However this is where I run into a problem with my setup, it's a little bit complicated:
I have entitities: CricketPlayer and CricketTeam... The user can create a CricketTeam object with an ordered array of CricketPlayer's which represents the batting lineup. When I next retrieve this list I want the lineup to be presented to the user in the same order in which they set it when creating a team... The only problem is within my app - the same goes in real life! - a player can play for more than one team so if I set an attribute on CricketPlayer say: batterNumber although this will enable me to re-create the batting lineup, if I then create another team with the same player in and bat him at a different position I will have ruined the batting lineup for the original team!
What I am therefore looking to do is create a 'pseudo-relationship' which is not a relationship to another CoreData entity but an attribute on an entity which depends on which entity it is being used within... so in my case I want an attribute on a CricketPlayer entity which represents that players batting number in a particular CricketTeam if that makes any sense at all!

You need a few more entities. I assume a player can play for a team more than once i.e. in more than 1 match, in a different order in the batting lineup. So you need a match entity which links CricketTeams, and record the batting order of the teams for that specific match.
Match
HomeTeamID
AwayTeamID
Team
TeamID
TeamName
Player
PlayerID
PlayerName
PlayerTeam
PlayerID
TeamID
MatchBattingOrder
MatchID
PlayerID
TeamID
BattingOrder
This is very simplistic! This is a data modelling issue

Related

Neo4j relationship property - array of values vs duplicate relationship

Lets say I have two nodes of type (: City).
Whats the better approach to store relationahip when some user walks from one city to another?. Please note that for this case we want to save day value (NOT daytime) and name of user.
Lets say that the same user walks between same two cities on 5 different day
What I have been thinking about is:
1) there will be a new relationahip each time when user walks from City(a) to City(b). However, that would create 5 different relationships with pretty much the same content (same user name in this case), only day value will be different.
2) there will be one relationship for each user and single data type(long) for property day will be replaced with an array of long values.
What do you think is better approach? Either create multiple relationships even if they share most of its properties, or create a one relationship with those shared properties and put variable ones into an array.
If you have any other ideas or suggestions please write them :)
Thanks
c.
In the spirit of the graphs, you can:
have a node for city
have a node for user
have a node for a fact of walking

Core Data Relationship For Unidirectional One to Many

What is the best practice for creating Unidirectional One to Many Relationships in Core Data?
For example...
Lets take two classic entity examples, "teacher" and "student".
Each student has one teacher, and each teacher has many students.
In CoreData right now you are forced to provide an inverse such that teacher is forced to have a reference to a 'student'. If you don't you get this nice warning that says something along the lines of...
file:///Users/josephastrahan/Documents/VisualStudioProjects/Swift3WorkOrders/WorkOrders/WorkOrders/WorkOrders.xcdatamodeld/WorkOrders.xcdatamodel/: warning: Misconfigured Property: Teacher.student should have an inverse
What if I don't want teacher to have a reference to student?
Some other posts have brought up that I should just allow the inverse anyways but I think this inverse may be causing an issue with one of my projects.
That said let me explain my exact issue.
Lets say that our teacher has a unique attribute int64 called 'id'. Lets say the students also have unique attribute int64 called 'id'.
The int64 is enforced to be unique by adding a constraint on the model for teacher on id. (refer to image below to see how that is done)
Every year there is new students but the teachers stay the same. So I decided that I want to delete all the students without deleting the reference to the teacher. So I set the delete rule to 'nullify' for the relationship for the teacher to student and 'nullify' for the student to teacher.
Now when I create a new student I want to assign one of the existing teachers to that student... (something like student.teacher = teacher object with id of 1 or the same id as before) however!! , because the teacher has the inverse relationship to a student that no longer exists (which in theory should be null) the program crashes!
I know this is the case as I've used print console logs to narrow it down the exact point that it occurs. Also I know this because if I add the delete rule of cascade for student the crash will go away but...then I lose my teacher! which I don't want...
Some things that I think might be the issue:
1.) When I do my testing I do it at the startup of the program which creates a new context everytime. Could it be that because I never deleted teacher it still thinks it refers to a student from a context that no longer exists? (if I'm even saying this right...)
I'm not sure the best solution to acheive what I'm trying to do with Coredata and any advice is much appreciated!
Note:
Forgot to mention I also have the Merge Policy of: NSMergeByPropertyObjectTrumpMergePolicy, which will overwrite the old data with the new. When I'm creating new students I'm creating new teachers also just using the same id which should follow this policy.
You are almost there.
The advice to keep the inverse relationship is a good one. Keep it.
Your issue is likely caused by different contexts. Instead of holding on to a teacher object in memory, you should fetch the teacher (based on the id) in the context in which you intend to use it.
Your nullified students should not have any impact. A to-many relationship is really a Set<Student>. Make sure the set is empty.
NB:
If you want to keep the student in the database (for historical purposes) - it seems from your description that this is the case - you might also consider another scheme: give your students another attribute (such as a year) and use that to filter the student list. You would not have to delete or nullify anything. You could also do some more interesting time-based queries on the data.
Unique Constraints are available with iOS9. Which have helped iOS Developers with adding and updating records in CoreData.
Unique Constraints make sure that records in an Entity are unique by the given fields. But unique constraints along with To-Many relationship leads to a lot of weird issues while resolving conflicts.
e.g. “Dangling reference to an invalid object.”
This post is basically focused to a small problem that may take days to fix.
http://muhammadzahidimran.com/2016/12/08/coredata-unique-constraints-and-to-many-relationship/

Core Data Model

I'm struggling with creating a suitable Core Data model for my app. I'm hoping someone here can provide some guidance.
I have two entities -- "Goals" and "Items". The Goals entity contains only a goal description, but any goal may have any number of subgoals, and these may extend multiple levels in a tree structure. Subgoals are to be contained within the same entity, so presumably the Goal entity will contain a pointer to "parent" which will be the parent goal of any subgoal.
There will also be an "Items" entity that contains a couple of text fields and a couple of binary items, and must be linked (ideally, by a unique identifier, perhaps objectID) to the particular goal or subgoal the item(s) are related to.
I am totally fumbling with how to set this model up. I know what attributes need to be in each entity, but the relationships, particularly between goals and "subgoals", has me stumped. I don't seem to be able to turn up any good examples of tree structures in Core Data on the Internet, and even the couple of books I have on Core Data don't seem to address it.
Can anyone here help an old SQL programmer get headed the right direction with these relationships in Core Data? Thanks.
Have you tried creating a one-to-many from Goal to itself, and a one-to-one from Goal to Item? The only thing I would worry about here is circular references.
Also, read Relationships and Fetched Properties in the CoreData Programming Guide.
Here is how it is done:
You set up a to-many relationship from Goal to Item in the model editor. Don't use any ids, foreign keys etc. This is old-fashioned database thinking - you can forget about it. Here we are only dealing with an object graph. The database layer is just an implementation detail for persisting the data.
Make two more relationships in entity Goal to itself: a to-one called parent, a to-many called subGoals. Make them the inverse of each other. Simple!
QED is correct, you can create a to many relationship on goal (call it subgoals) as well as a to-one relationship on goal (call it parentGoal) and set them as inverses to each other.
Then create another to many relationship (call it items) on the goal entity, with the inverse being a to one relationship on the item entity (call it goal). Then you're all set. You don't need to link items with a unique id, just add them to the items relationship.
Also note that if you did want to give items a unique id, do not use the objectID. The objectID should only be used as a temporary id as they are not guaranteed to remain the same. In fact they will change if you ever do a Core Data migration.
One way, though not really great, is to create a another entity, say subGoal, and each goal has one subGoal and each object of subGoal has many goal.

How to have repeated items in an Ordered To-Many relationship?

In Core Data of Xcode 4.3.2, an Ordered To-Many relationship is modelled with NSOrderedSet. It works well until I found the need to have repeated items in the relationship; it should really be modelled in a NSArray.
For example, in a music app, I have the following songs: SongA, SongB, SongC ,
I may want a party play list where people insert songs in any order and could be repeated. The list may look something like:
[SongC, SongC, SongA, SongC]
The way Core Data currently works, the list would become:
[SongC, SongA]
I.e., all repeated items are dropped, as it is modelled with sets.
So, coming back to my question: what is a good way to model repeated items in order in a relationship in Core Data?
Relationships are sets (and ordered relationships are ordered sets, but still sets); sets by definition contain unique objects. So you can't put duplicate objects into a relationship either way.
Whether you use the ordered-relation feature or not, you'll want to go back to the abstract ER model to find another way to turn your conceptual relationships into a Core Data model... it might help to think about how you'd do it in a plain SQL (or SQL-like) database and then come back to what Core Data does beyond SQL.
It sounds like you're making something akin to iTunes playlists, no? A model that might work for that would go something like:
Playlist <--->> PlaylistEntry
PlaylistEntry <<---> Song
The PlaylistEntry entity represents one instance of a Song's inclusion in one Playlist. You can have multiple PlaylistEntrys that reference the same Song in a single Playlist, and you can add other attributes to the PlaylistEntry to keep track of other things (like song order, if you're not using an ordered relationship). As a bonus, you can use that to add other features if you like -- say, to make a playlist that plays three different snippets out of one long track.
As rickster said, relationships as managed by Core Data uniquely associate entities between them. Even if Lion's Core Data (is supposed to) supports ordered relationships (supposed to, because in practice it won't work, the feature is buggy, barely usable), they still are relationships that follow the relational database model.
And so you have to manage the association by yourself, and you most certainly have to manage the ordered part of the association by yourself too.
Score <->> ScoreSong
ScoreSong <<-> Song
With ScoreSong having the following properties:
ScoreSong:
- score: -> Score
- song: -> Song
- order: integer, indexed
Then you have to use a Fetch Request with a sort descriptor for the key order, which will return an ordered NSArray of ScoreSong. You can ask the fetch request to prefetch the songs, then you can create the songs array, still properly ordered, with a single call to valueForKey: #"song".
Of course you have to create different ScoreSong for a single Song when you need to include than song more than once in your Score. That's the whole point of the added indirection.

How do I model teams, games, and home/away team relationships within Core Data?

I am trying to use Core Data to represent a sports league's schedule. Within my model I have an entity called Team and an entity called Game. Each team will have many games. Each game will have two teams, one that is identified as the home team and the other that is identified as the away team.
In my current approach I have defined "homeTeam" and "awayTeam" relationships within the Game entity. Each of those relationships are to-one and have their destinations set to the Team entity. I have also defined a to-many "games" relationship within the Team entity that has its destination set to the Game entity.
The problem with this approach is that I can't set the inverse relationships in any appropriate way. It would require the Team/games relationship to be the inverse of both the Game/homeTeam and the Game/awayTeam relationships, and that isn't allowed (as far as I can tell). I could of course define these as unidirectional relationships but I start getting Xcode warnings and I'm not sure that's a good thing to do here.
I've also considered removing the awayTeam and the homeTeam relationships from the Game entity and replacing it with a teams relationship. That relationship would be many-to-many with Team, with a min and max value of 2. However, the approach doesn't allow me to distinguish between the home team and the away team, which I will need to do in my app.
I'd appreciate any recommendations for the best way to represent these kind of relationships within CoreData. I could no doubt implement this myself using my own DB layer, but I'd rather rely on CoreData than come up with a home-grown solution here.
Here is how I would do it:
Game has two one-to-one relationships, homeTeam and guestTeam.
Team has two one-to-many-relationships, homeGames and outGames. The inverse of homeGames is homeTeam, and the inverse of outGames is guestTeam.
Makes sense?

Resources