I'm using CoreData for the first time in one of my project. My table involves FOREIGN KEYS and since CoreData doesn't support FOREIGN KEYS, I'm having some issues.
Below is the structure of my tables.
My Problem is the establishment attribute.The establishment attribute is supposed to hold the name of a particular facility from the Facilities table. However, since it's a relationship, Xcode expects a Facility rather than just a name of a facility (NSString).
Is this possible, or am I just mixing up FOREIGN KEYS with RELATIONSHIPS in CoreData? How would I solve this problem?
Thanks in advance.
A relationship is not a property, so it does not have a type. In the model editor you add a relationship explicitly.
From your diagram, I see that you did not set the inverse relationship. There needs to be a corresponding relationship from name to the Assessors entity. (Set the "Destination" to Assessors in the model editor.)
I would also suggest to rename a few items.
First, use singular: Assessor, Facility. These are objects (comparable to classes), not tables.
Second, because your name attribute refers to an assessor, call it assessor, and similarly call its reverse relationship facilities (it is a to-many relationship in this direction, so the plural is appropriate).
If you need the name of the assessor of a facility, you use
facility.assessor.name
This should make it obvious why you do not need foreign keys. Indeed, I would urge you to think that it is not Core Data that does not support foreign keys, but that it is the traditional relational databases that do not support relationships!
Related
I was interested in storing the history of properties which contains two entites - properties and owners. Right now I am not sure what approach to take and needed some help.
I was thinking of creating an associative entity and so this would have its identity a combination of property and owner but the textbook comes up with this solution instead:
Solution
What's the difference between the solution above and an associative entity?
The owns table in the given solution would be called an associative entity set in the network data model. This data model supports only one-to-one and one-to-many binary relationships, and resolves many-to-many binary relationships as well as ternary and higher relationships into an associative entity set with binary one-to-many relationships.
However, in the entity-relationship model, the owns table represents a many-to-many relationship relation. The ER model directly supports many-to-many binary relationships as well as ternary and higher relationships, and uses "associative entities" to refer only to relationships which are the subjects of other relationships.
The only databases I've worked with before are MySQL so the database design of CoreData is confusing me a little bit.
Briefly, the design consists of a many-to-many relationship between people and businesses. Many people can own one business. One person can own many businesses.
In this simplified design, there are 3 tables:
PERSON BUSINESS OWNED BUSINESS
------ -------- --------------
id id personID
name name businessID
email website acquisitionDate
The OwnedBusiness table is the one that's confusing me. In MySQL, this table is used to support many-to-many relationships. I understand that CoreData doesn't require this, however I have an extra field in OwnedBusiness: acquisitionDate.
Does the extra field, acquisitionDate warrant the use of the extra entity/table? If not, where would that field go?
First, Core Data is not a database, full stop.
Core Data is an object graph management framework, your model in your application.
It can persist to disk in a database. It can also persist as binary, XML and just about anything else. It does not even need to persist.
Think about Core Data as an object graph only. In your example you would have a Person entity, a Business entity and a OwnedBusiness entity.
The OwnedBusiness entity would have two relationships and one property. You would not manage the foreign keys because Core Data handles that if you end up persisting to a database. Otherwise they are object pointers.
So first of all, CoreData is not a relational db just to clear this out.
Second, I think you should have a quick look at CoreData documentation and since you are familiar with MySql it will be an easy reading and I think you will be kind of amazed by the extra features that CoreData provides.
Regarding the many-to-many relationship, CoreData support this relationship without the need of extra tables. Also the relationship are not based on ids, they are based directly on objects.
So in your case, you don't have to use the person id & business id to create the relationship, you can create the relationship in the Relationship section of your xcdatamodel, there you can set the relationship class (or Destination), an inverse to that relationship (useful thing) and of course the type of relationship (to-many, to-one).
So to answer your question, you can add it there depending on your business logic. As a short advice, pleas don't try to normalise the database as you would do on a normal MySql instance, you will loose lot of performance by normalising, this thing is often ignored by devs.
I have 2 entities in my domain that have a one-to-one relationship with one another.
Entity Business has a Promotion. And Promotion has a Business. I know this doesn't make a lot of sense and I could as well integrate the fields of Promotion into my Business entity, but I'm dealing with a legacy database here and I'm trying to model my domain on top of it without changing anything in the database for now.
My problem is that although the relationship goes both ways, it's only stored on the side of the promotion table that has a business_id foreign key, but there is no promotion_id foreign key in the business table. So when I try to run my app, Grails can't find the promotion_id column it expects to find for the promotion field in Business.
Is there any way to model my domain entity so that it understands that the column for the relationship is in the destination table only?
Right after I asked this question, I found my own answer: using hasOne as explained in http://grails.org/doc/latest/ref/Domain%20Classes/hasOne.html
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.
I have a MySQL database and would like to have a similar structure in Core Data. I am very new with using Core Data with Xcode. I have a few fundamental questions if I am doing the right thing.
My Mysql DB looks similar to this:
table.caveconditions
visibilityID
percolationID
xxxx
table.visibility
visibilityID
visibilityValue
...and so on. I would then connect the tables using JOINS
Now, I have done the Core Data modeling like this but I am not quite sure if this is the right approach.
Would be great if someone of you could tell me if this is the right way to do it. In the end I would like to use JSON strings to dump the mysql table into core data.
Thanks a lot
Chris
I have created the new schema. Is this right?
It looks good except for all the "xxxID" attributes e.g. caveID. You also need to follow the naming conventions.
You have the same attribute names with (presumably) the same values in two or more entities. This is necessary in SQL for joins but in Core Data, this is handled by objects and relationships.
Each object in Core Data is automatically universally unique. This means when you create a relationship from one object to another, that relationship concrete identifies on specific unique object.
This means you only need an attribute like caveID in the actual entity that caveID designates which in this case is (presumably) the Caves entity. You don't need the attribute in the CavesConditions entity or any other entity that has a relationship to the "Caves" entity.
(If the xxxID were just artifacts of SQL, you don't actually need them at in Core Data unless some external database your app interacts with requires them.)
A good rule of thumb to use is that any particular value should show up on only one side of a relationship and, ideally, only once in the entire data model.
Naming conventions are a little different than SQL. A Core Data entity isn't a table. An entity is more akin to a class. Each entity is supposed to describe a single instance of a managed object. How many of those instances end up in the object graph is irrelevant. Therefore, entity names are singular.
In this case, Caves should be Cave, Countries should be Country and so on.
Relationships are named after the entity they target. It is not immediate obvious but each reciprocal relationship (the default) on the visual data model editor is actually two relationships because there is one relationship description for each side. Each side has the name of the entity targeted. By convention to-one relationships have a singular name and a to-many relationship has a plural name.
So:
Caves.relConditions<-->>CaveConditons.getCave
...would become
Cave.conditons<-->>CaveConditon.cave
The naming conventions are important because Objective-C uses conventions names to generate and search for accessor methods.
CoreData is NOT a database. Remodel your data as simply as you can and in a way that suits how it will be used in your application and do not think about joins or structure based optimization. You do not have control over the backing schema of a CoreData object model. This is the hardest concept you must get over when starting to use CoreData, but once you do, you will be better off.