Core data for SQL users

Hi,


I have read many tutorials about Core data.

Unfortunately I can't understand some of the way it works.

For instance , I have two Entities Sale and Products.Coming from SQL I thing that I have in each sale to have a reference to products.

How ti happens in Core data.I see some relations, but what exactly they relate?And where we bind the values from particular column from peoducts with sales?

How we make left joint search?

From my current experiance I find Core data very anoyng, but from the other side I know that millions of people use it, so the dumb shoould be me.


Thank you in advance of all that help!

Answered by NotMyName in 229895022

"What's the deal with relationships in CoreData?"

Relationships in CoreData are used instead of SQL's foreign key references. Core Data hides all of the details about whether those relationships are implemented using foreign key references, and updating those references. To be a bit blunt about it, the deal with relationships in CoreData is to make it so that someone else does all of your joins for you.


"How we make left joint search?" Part of the point of relationships in Core Data is that you don't have to ever manually do a left join search again. If you have to entities related by a one-to-one relationship, you just include the relationship in the key path. And for the cases where you'd want to execute a query to find all of the SaleRecord for a given Sale yourSale, you'd just do the fetch request

"sale = %@", yourSale

with the entity for the fetch request set to SaleRecord.


Let's take your example of a Sale and Product entities, and let's skip to the discussion of a non-trivial sale record, so that your Sale refers to multiple SaleRecord entries, and each SaleRecord entry is:

  • Sale ID (so you can do your left join on Sale)
  • Product ID (so you can do your left join on Product)
  • quantity

In other words, the sort of thing you'd need to use if you wanted to sell someone 2 of Widget A, and 1 of Widget B.


In SQL, your Sale table would have a Sale ID as its primary key, and SaleRecord would have the Sale ID as a foreign key reference.

In Core Data, SaleRecord looks like this:

  • sale (relationship to Sale, to-one.)
  • product (relationship to Product, to-one.)
  • quantity (attribute, integer)


In Core Data, every entity has its own system generated ID that the framework generates. Those system ID's get used to implement the relationships, so the ID's that you want to include out of SQL-driven habit aren't needed and don't get used. So you eliminate the Sale ID from your Sale. Instead of that, what you usually want to do is have a relationship from Sale to SaleRecord to do two things:

  • If you want to get an array of all of the SaleRecords for a Sale, it's as simple as "yourSale.saleRecords"
  • Setting Sale's saleRecord relationship to be the inverse of SaleRecord's sale relationship lets CoreData take care of maintaining both sides of the relationship, and makes it less work for you when you add new members of a to-many relationship.


To try to list everything at once....


SQL:

  • Sale

    Sale ID (primary key)

  • SaleRecord
    • Sale ID (foreign key reference)
    • Product ID (foreign key reference)
    • quantity
  • Product

    Product ID (primary key)


Core Data:

  • Sale

    saleRecords (to-many relationship to SaleRecord, inverse of sale)

  • SaleRecord
    • sale (to-one relationship to Sale, inverse of saleRecords)
    • product (to-one relationship to Product, inverse of saleRecords)
    • quantity
  • Product

    saleRecords (to-many relationship to SaleRecord, inverse of product)


That's leaving off all of the fiddly attributes like product descriptions, prices, and so on, just putting quantity in there to avoid making the example trivial. I think recent versions of Core Data have added the option to add other attributes (in addition to the system-generated entity ID) as an entity's primary key, but I don't think that changes anything in the fundamentals of how relationships work, but just trying to give you that 'I want to ensure this attribute value (or attribute values) is/are unique' support you had in SQL tables.

Accepted Answer

"What's the deal with relationships in CoreData?"

Relationships in CoreData are used instead of SQL's foreign key references. Core Data hides all of the details about whether those relationships are implemented using foreign key references, and updating those references. To be a bit blunt about it, the deal with relationships in CoreData is to make it so that someone else does all of your joins for you.


"How we make left joint search?" Part of the point of relationships in Core Data is that you don't have to ever manually do a left join search again. If you have to entities related by a one-to-one relationship, you just include the relationship in the key path. And for the cases where you'd want to execute a query to find all of the SaleRecord for a given Sale yourSale, you'd just do the fetch request

"sale = %@", yourSale

with the entity for the fetch request set to SaleRecord.


Let's take your example of a Sale and Product entities, and let's skip to the discussion of a non-trivial sale record, so that your Sale refers to multiple SaleRecord entries, and each SaleRecord entry is:

  • Sale ID (so you can do your left join on Sale)
  • Product ID (so you can do your left join on Product)
  • quantity

In other words, the sort of thing you'd need to use if you wanted to sell someone 2 of Widget A, and 1 of Widget B.


In SQL, your Sale table would have a Sale ID as its primary key, and SaleRecord would have the Sale ID as a foreign key reference.

In Core Data, SaleRecord looks like this:

  • sale (relationship to Sale, to-one.)
  • product (relationship to Product, to-one.)
  • quantity (attribute, integer)


In Core Data, every entity has its own system generated ID that the framework generates. Those system ID's get used to implement the relationships, so the ID's that you want to include out of SQL-driven habit aren't needed and don't get used. So you eliminate the Sale ID from your Sale. Instead of that, what you usually want to do is have a relationship from Sale to SaleRecord to do two things:

  • If you want to get an array of all of the SaleRecords for a Sale, it's as simple as "yourSale.saleRecords"
  • Setting Sale's saleRecord relationship to be the inverse of SaleRecord's sale relationship lets CoreData take care of maintaining both sides of the relationship, and makes it less work for you when you add new members of a to-many relationship.


To try to list everything at once....


SQL:

  • Sale

    Sale ID (primary key)

  • SaleRecord
    • Sale ID (foreign key reference)
    • Product ID (foreign key reference)
    • quantity
  • Product

    Product ID (primary key)


Core Data:

  • Sale

    saleRecords (to-many relationship to SaleRecord, inverse of sale)

  • SaleRecord
    • sale (to-one relationship to Sale, inverse of saleRecords)
    • product (to-one relationship to Product, inverse of saleRecords)
    • quantity
  • Product

    saleRecords (to-many relationship to SaleRecord, inverse of product)


That's leaving off all of the fiddly attributes like product descriptions, prices, and so on, just putting quantity in there to avoid making the example trivial. I think recent versions of Core Data have added the option to add other attributes (in addition to the system-generated entity ID) as an entity's primary key, but I don't think that changes anything in the fundamentals of how relationships work, but just trying to give you that 'I want to ensure this attribute value (or attribute values) is/are unique' support you had in SQL tables.

Thank you very ,uch for you time!

It was very helpfull.Now I find Core data very usefull and much easier than SQL!

I have some additional questions:

I make some test with two entities Products and Sale.

The interesting is that when I set relationship @products in Sale which hold the product and I create a new sale after than I go to the Products and edit the same product that was sold.The result is that the product in Sale doesn't change.This means that it holds no reference , but the entire product, right?

"The interesting is that when I set relationship @products in Sale which hold the product and I create a new sale after than I go to the Products and edit the same product that was sold.The result is that the product in Sale doesn't change.This means that it holds no reference , but the entire product, right?"


If I understand what you're asking, then the answer is as follows:

- Inside the same managed object context, Core Data works to ensure that you only have one NSManagedObject instance for any given entity in storage. So if you get a reference to the object for the Product with object ID X in two or three different lines of code but each accessing the same managed object context, each of lines of code is going to return the same instance of Product. So you end up with different variables referencing the same object instance, and naturally you see the changes locally immediately.


Very importantly, all of the different ways you can get an NSManagedObject instance in a context are subject to that uniqueness mechanism. So if you execute a fetch request that happens to have the Product with object ID X in it; that's going to be the same Product instance that you get if you called existingObjectWithID:. Whether or not you know you're asking one context for the same object with ID X in different places, the context knows and will ensure that there's only once managed object instance that it gives out for ID X.


- If you access the Product with object ID X in two different managed contexts, then you get a different unconnected instances of Product. So you end up with different variables referencing different objects and changes to one instance won't be seen in the other instance until you merge the changes from one managed object context to the other, or otherwise synchronize the contexts.

Core data for SQL users
 
 
Q