7
votes

I'm trying to set up a simple Core Data model like the following:

Order(code, customer)
Book(code, title, price)
OrderBook(order_code, book_code, quantity)

From Core Data documentation I see that it's not possible to model a many-to-many relationship adding to it attributes. For this reason I modeled it like the following.

enter image description here

where:

  • from Order to OrderBook there is a one-to-many relationship with a delete rule Cascade
  • form OrderBook to Order there is a one-to-one relationship with a delete rule No Action

The same is valid for Book and OrderBook.

First question: Is this model valid?

Supposing that the model is ok, I created the corresponding NSManagedObject subclasses.

Book.h/.m
Order.h/.m
OrderBook.h/.m

That said, I have the necessity to populate the corresponding db by means of Core Data mechanism. To do this I created the corresponding categories like the following, where each category is responsible to create itself (to maintain object encapsulation).

Book+Creation.h/.m
Order+Creation.h/.m
OrderBook+Creation.h/.m

For example Book+Creation category has a class method like the following:

+ (Book *)bookWithXMLElement:(GDataXMLElement *)xmlElement inManagedObjectContext:(NSManagedObjectContext *)context;

Now I have a problem and I don't know how to resolve it.

The model population has to happen at different times. The table for books is populated first (I'm creating a catalog of books from an xml file). Once finished, I'm able to populate order and orderbook tables. To populate these tables I'm using an xml file like the following:

<orders>
  <order>
     <code>1234</code>
     <book>2567</book>
     <customer>299</customer>
     <quantity>4</quantity>
  </order>
</orders>

To create an Order managed object I've created the following method in its category Order+Creation:

+ (Order *)orderWithXMLElement:(GDataXMLElement *)xmlElement inManagedObjectContext:(NSManagedObjectContext *)context;

Once created, the object is passed to OrderBook+Creation class method category to create an OrderBook managed object:

+ (OrderBook *)orderWithXMLElement:(GDataXMLElement *)xmlElement withOrder:(Order*)order inManagedObjectContext:(NSManagedObjectContext *)context
{
  OrderBook* orderBook = [NSEntityDescription insertNewObjectForEntityForName:@"OrderBook" inManagedObjectContext:context];
  orderBook.order = order;
  //orderBook.book = <-- how can I retrieve the book?

  return orderBook;
}

What is missing is how to create (or retrieve) the Book object to assign it to OrderBook object.

Second question: How can I retrieve a Book object and assign it to OrderBook? Do I have to create a NSFetchRequest to fetch the right object Book (the one that has the same code in xml file, e.g. <book>2567</book>)? If so, is there a mechanism to improve performance for the fetching rquest?

Remember that book table is already populated.

Hope it is clear. Thank you in advance.

1
With your current model, if you have an order book object which has both a book and and order attribute, if you delete either the book or the order, the order book object will be removed. Is that what you want?jrturton
@jrturton thanks for your reply. Yes,it's what I want. Do you have any suggestions?Lorenzo B
@jrturton Deleting an order or a book, the order-book obj (the order-book row, speaking in db terms) also will be deleted.Lorenzo B

1 Answers

3
votes
  1. Should be "nullify" not "no action" for the to-one relationships.
  2. Yes, you're right, you need a fetch request.

If you have performance problems with the fetch request (hard to say without knowing the numbers involved) you could fetch the whole set of books into memory (again, might not be practical depending on the numbers) and then use array filtering/enumeration to find the specific item, but you should definitely build and profile the simplest option first.

The delete rule types are described here, nullify is correct for the to-one relationship from orderBook to Book and Order:

Nullify

Set the inverse relationship for objects at the destination to null.

For example, if you delete a department, set the department for all the current members to null. This only makes sense if the department relationship for an employee is optional, or if you ensure that you set a new department for each of the employees before the next save operation.

This means if you delete an orderBook, then it is removed from the orderBooks and bookOrders sets in the Order and Book entities.