Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Core Data From Combining Entities into One Table

Is there a way to tell Core Data to not put all your entities into one table when they all inherit from a base entity? Here's an example: We have an "Entity" object and we have a "Person" and "Product" that inherit from "Entity". Core data creates an ZENTITY table with the combined fields for "Entity", "Person" and "Product". What we want is for core data to create two separate tables, one for "Person" and one for "Product".

Is this even possible? Nothing anywhere online talks about this...

like image 383
jjxtra Avatar asked Mar 11 '11 17:03

jjxtra


People also ask

What is constraints in Core Data?

Constraints in Core Data are part of an entity configuration. Settings like the entity name and Spotlight display name might be easy to understand while constraints are a bit less known. However, they can be super useful to maintain a unique set of data.

Can we set primary key in core data?

The answer is NO.

What is entity in core data in Swift?

An entity describes an object, including its name, attributes, and relationships. Create an entity for each of your app's objects.


4 Answers

Nothing anywhere online talks about this..

That's because tables have nothing to do with Core Data.

Core Data is not SQL. Entities are not tables. Objects are not rows. Columns are not attributes. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.

In this, case your SQL trained intuition for how to optimize SQL will cause you to waste a lot of time. If your peaking into your SQLite store as you develop, you are using Core Data incorrectly. It's not just an object wrapper for SQL.

It was a design decision to put all entities with the same inheritance into the same SQL table when Core Data is using an SQLite store. However, that has little functional relevance in most cases as Core Data manages the object graph first and cares little about the details of persistence. If you have a large number of objects of the same entity inheritance tree you might hit some performance issue at the very high end e.g. 20k+ objects but otherwise not.

In any case, it can't be changed. Core Data intentionally hides the its SQL implementation because SQL is just one persistence option out of many.

Premature optimization is the root of all evil. Build in the logically best fashion and then test. Only if you encounter an edge case in testing should you worry about the minutia of the SQL store.

like image 59
TechZen Avatar answered Oct 17 '22 05:10

TechZen


According to the detailed article by Florian Kugler, the solution is to use inheritance in your model code but not in your schema:

Entity Hierarchy vs. Class Hierarchy

Managed object models offer the possibility to create entity hierarchies, i.e. we can specify an entity as the parent of another entity. This might sound good, for example, if our entities share some common attributes. In practice, however, it’s rarely what you would want to do.

What happens behind the scenes is that Core Data stores all entities with the same parent entity in the same table. This quickly creates tables with a large number of attributes, slowing down performance. Often the purpose of creating an entity hierarchy is solely to create a class hierarchy, so that we can put code shared between multiple entities into the base class. There is a much better way to achieve this though.

The entity hierarchy is independent of the NSManagedObject subclass hierarchy. Or put differently, we don’t need to have a hierarchy within our entities to create a class hierarchy.

https://www.objc.io/issues/4-core-data/core-data-models-and-model-objects/

like image 23
Chris Conover Avatar answered Oct 17 '22 06:10

Chris Conover


I did measurements and CoreData's performance is totally degraded when using inheritance on real (~50000 objects, 20+ classes, each having ~5 relationships, most of them to-many) data. I do not use CD for toy apps with 1000 objects - it's a real huge app and performance penality is unjustified. Even worse, creating small objects takes lots of ssd and memory space because of this stupid implementation.

The only real solution (i DO NEED inheritance) is to replace the default sqlite persistent store with manual implementation using NSIncrementalStore from iOS 5 and up. However, fetch request to SQL translation and model updates are really hard to implement.

And yes, I know that core data is not an SQL. But I expect it to work comparably fast when dealing with lots of data - otherwise it would be stupid to ever use it in real world apps.

like image 31
Terminus Avatar answered Oct 17 '22 06:10

Terminus


Seems it is an old question, but I still hope I can help others who have same issue.

I found a good answer from this URL: https://www.objc.io/issues/4-core-data/core-data-models-and-model-objects/#entity-hierarchy-vs-class-hierarchy.

In order to avoid the url become invalid in the future, I posted some important content here:

For example, we have authors and books which are inherited from BaseEntity. What we should do is designing Entities as they should be, not using inheritance.

Entity hierarchy            Class hierarchy
----------------            ---------------
 Authors  Books               BaseEntity
                               |      |
                            Authors  Books

The code should be like this:

@interface BaseEntity : NSManagedObject
    @property (nonatomic) int64_t identifier;
    @property (nonatomic, strong) NSDate *createdAt;
    @property (nonatomic, strong) NSDate *changedAt;
@end

@interface Author : BaseEntity
    // Author specific code...
@end

@interface Book : BaseEntity
   // Book specific code...
@end
like image 26
Stone Avatar answered Oct 17 '22 06:10

Stone