Load automatically entity of core data relationship - ios

I have two entities A and B between which there is a 1 to n relationship (A-1---n->B). What I want to achieve is that whenever an entity A is recovered is also be automatically retrieved a specific entity B belonging to the relationship. I could think of is to create a subclass of NSManagedObject and modify it to achieve my goal but I do not know how to do that and whether it is the right solution.

You can get XCode to automatically generate an NSManagedObect subclass for you by going to the Editor drop down menu. Once you've generated the subclass, you can write any custom code into the generated subclass but it's often recommended to create a Category as if you need to regenerate the subclass it will wipe said custom code.
As for the retrieving of a specific entity B, you could have another relationship to entity B but this time just a 1 to 1 relationship (say "specialRelationship" for example) and tick the "transient" box (this just means that the data isn't stored in the persistent store, but is determined programmatically). In your Category, you can then write a custom accessor for specialRelationship which will programmatically choose the correct entity B to return.

Related

Model structure when entities having some properties in common

I have 2 entities in Core Data which have some common properties. I have to show both the entities in a same list view. What will be the best practice to do this? Can I do some inheritance thing and put common properties in base class?
Core Data supports inheritance.
Open your core data model and select the child entity. Make sure the utilities pane is displayed (top right button in Xcode) and select "Show the data model inspector" (right most icon in the utilities pane).
Here you can select a parent entity for your entity. All attributes of the parent will be available in the child entity.
Apple documentation on Core Data inheritance
What will be the best practice to do this?
It depends on what type of entities you need to model. For example, if you have a Cat and a Dog, you should move the attributes in common in a base entity (say Animal or whatever you want). In other words, you should have a reason for doing this, i.e. entities have a sort of relationship each others.
Can I do some inheritance thing and put common properties in base class?
Yes of course. In a model you are allowed to have a sort of inheritance pattern like the following.
where
I would stress two things here.
First, you can make base entity as an Abstract Entity. In this way, you are not allowed to create instances of this entity.
As per the doc.
You can specify that an entity is abstract—that is, that you will not
create any instances of that entity. You typically make an entity
abstract if you have a number of entities that all represent
specializations of (inherit from) a common entity which should not
itself be instantiated. For example, in a drawing application you
might have a Graphic entity that defines attributes for x and y
coordinates, color, and drawing bounds. You never, though, instantiate
a Graphic. Concrete sub-entities of Graphic might be Circle, TextArea, and Line.
Second, under the hood Core Data will create a single table with all the attributes you have inserted. So, if you have a lot attributes, you will have a lot of columns for a table.

Exclude Models from being saved with Breeze

I have EntityA which has a navigation property to EntityB. In the frontend it's possible to create a new EntityA and append it to EntityB. If I now try to save the new created EntityA, Breeze also want's to save the changes on EntityB (containing the new ID of the newly created EntityA). Is it somehow possible to avoid having EntityB, because in this specific use case it should be possible to append new entities to EntityB, but these should not be saved back (and also not be reported as pending changes)?
I see the possibility with using two EntityManagers, but this would mean that I can no longer have navigation properties between the two types.
Pascal is asking an important question: are Entity A and Entity B related one-to-one? More to the point are they related one-to-one such that A depends on B (i.e. A is a child of B)?
A typical relationship of this sort is the "extension" entity. Consider "Order" and "OrderExtension". "OrderExtension" is a bolt-on type with optional fields that "extend" the core order data. An order can have zero or one "OrderExtension" records.
Order is the parent in this example; it SHOULD NOT have a FK reference to the OrderExtension. The OrderExtension is the child and it SHOULD HAVE a required OrderID FK field. The parent Order can exist without a child, but the child OrderExtension cannot exist w/o the parent.
At least that's how I think it should be. I've often seen folks turn this around. They give the Order an OrderExtensionID FK field which is optional. The OrderExtension has no backpointer to the Order.
The weakness of this design is that it allows you to create multiple orphaned OrderExtension entities that don't belong to anything ... and you'll rarely know they are there.
I'm betting that's your situation. I'm betting that Entity B is like OrderExtension and Entity A is like Order. When you created the OrderExtension (B) and associated it with an Order (A), Breeze tried to maintain that relationship for you by updating the Order.OrderExtensionID property. That puts Order (A) in a modified state.
DO not proceed until you've figured this out. While Jeremy is correct that you can save one entity by cherry picking the pending changes - you can save B without saving A -, you risk breaking the integrity of your data!
From a modeling perspective you've made Entity A dependent on Entity B. If you don't save A at the same time you save B, there will be no way for someone using the database to know that the two are related.
Next time you query for either of them, neither you nor Breeze will know they are related. You will be unable to navigate between A and B. I'm pretty sure that's not what you had in mind.
You can pass an array containing the entities you wish to save to the saveChanges method to restrict which entities are saved.
From the breeze docs:
saveChanges ( [entities] [saveOptions] [callback] [errorCallback] ) async
Saves either a list of specified entities or all changed entities
within this EntityManager. If there are no changes to any of the
entities specified then there will be no server side call made but a
valid 'empty' saveResult will still be returned.
Parameters:
[entities] Array of Entity optional The list of entities to save.
Every entity in that list will be sent to the server, whether changed
or unchanged, as long as it is attached to this EntityManager. If this
parameter is omitted, null or empty (the usual case), every entity
with pending changes in this EntityManager will be saved.

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.

Search by properties of two Entities (fetch from two Entities)

Let's say I have two entities, A and B. My goal is to implement the search by all properties of A and just one property of B, and to display sum of search results in one tableView. Naturally I can set fetchRequest only by one entity. But if I am understand right I can fetch not only from A but from B too if they are connected with relationships.
So what do I need to do to implement this? Does default fetch fetches all properties from A and B? If not, how can I specify fetch of all properties from A and one property of B in one fetch?
Issue solved.
At the stage of preloading data from JSON file into Core Data I am define getters for properties (prefetching data from entity)in B and setting entity properties of A equal to returned results of this getters (all this in NSManagedObject subclasses inherited from entities). So after that I am able to fetch all what I need using this getters through appropriate properties.

Core Data cascade on Data Inserts

I'm currently learning to use Core Data on iOS , in my test application I have two entities with an inverse relation, the delete cascade is working fine but i wonder if it is possible to have a update or insert cascade as well? for example if I create a new instance of entity 1 i want some of its attributes to be copied onto a new object of entity 2.
Do I have to write some code for this or is there some built in solution?
searching the internet gave me no results.
(also since I'm new to Core Data i'm thinking in terms of tables as my persistent store is of SQLite so an insert into one table must essentially copy a few attributes into another table)
Try to think of it in a different way. If those two objects share those properties, perhaps it would be best to create another entity who contains those fields and entity 1 and entity 2 would both have a common relationship to. Having multiple copies of the same data just doesn't seem like a good idea where it can be avoided.
(You haven't mentioned multiplicity of the relationship, which could be important.)
Not sure if this directly addresses your question, but …
If you have A <--> B. (1-to-1 relationship)
Cascade rules:
A cascades: B
B nils: A
(this is an A "owns" B description)
(above A/B == entities, below A/B == instances of entities)
if A(1) -> B(2)
and then you set
A(3) -> B(2)
B(2)'s reverse relationship to A(1) is nil'd out before it's set to A(3)
A(1) is left with a nil value (if that's not valid in the data model description, you're now in trouble, otherwise, it's B-less)
A(1) -> <nil>

Resources