Core Data predicate with multiple to-many operations - core-data

Apple's Predicate Programming Guide describes a limitation on Core Data predicates:
The Core Data SQL store supports only one to-many operation per query;
therefore in any predicate sent to the SQL store, there may be only
one operator (and one instance of that operator) from ALL, ANY, and
IN.
I just tested this by creating a fetch request with a compound predicate with two ANY operators in it (wanting to return any objects matching two separate to-many relationships. The request appears to have worked, returning the object I was expecting.
So, is the statement in the guide:
incorrect (or out-of-date)
correct (appears to work, but won't be deterministic, so can't be trusted)
correct (appears to work, but my test is shoddy)
correct (for some other reason)
Thanks

Related

Core Data: storing ordered values in a one-to-many relationship

I'm building a workout app that has an entity called Workout and another one called Exercise.
A workout can contain multiple exercises (thus a one-to-many relationship). I want to show the users of my app the exercises contained in a workout but in an ordered way (it's not the same to start with strength exercises as with the cardio ones).
Apparently, when establishing this kind of relationship in Core Data, I need to use an NSSet, because if I try to use for example an Array where its elements are ordered, I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-many relationship: property = "consistsOf"; desired type = NSSet; given type = __NSArray0; value = (
).'
I have tried to check the "ordered" checkmark in my model, but then I get an error saying "Workout.consistsOf must not be ordered".
I have also tried to use an NSDictionary whose keys would be the position and the values would be the exercises themselves, but I'm getting the same error as above.
How can I show the users the exercises that a workout consists of in an ordered way?
Thanks a lot in advance!
P.S.: Here's a screenshot of the properties of my model.
Ordered relationships use NSOrderedSet, but CloudKit doesn't support ordered sets, so you can't use an ordered relationship and CloudKit in the same data model.
To keep an order, you need to have some property on Exercise that would indicate the order. This could be as simple as an integer property called something like index. You'd sort the result based on the index value. If there's something else that also indicates order-- like a date, maybe?-- use that instead of adding a new property.

How to compare entity identity in Core Data

What is the preferred way to compare two Core Data entities for identity in the same context?
Is it OK to just use object identity and do EntityOne == EntityTwo as long as I'm sure they're both in the same context? That is, am I guaranteed that for each Core Data entity, a maximum of one Cocoa Object representation exists per ManagedObjectContext?
If not, what is the preferred way? In my model, every Core Data Entity has a UUID property anyway, I'm sure that one is safe (but also slower) to compare. What's the best practice here (and for posterity, what if one's model doesn't have the UUID?)
How about comparisons across contexts? [EntityOne inContext:moc] == [entityTwo inContext:moc] or similar, or is there a faster/better/more elegant way?
If you want to know whether two managed objects represent the same underlying instance, the correct approach is to compare their objectID properties using isEqual:.
If the two objects were fetched from the same context, they're actually the same object, because Core Data doesn't create multiple objects for the same instance in the same context. Using == should be fine in that strictly limited case. Using == in any other situation will give incorrect results.

How to achieve data polymorphism for multiple external formats in Haskell?

I need to process multiple formats and versions for semantically equivalent data.
I can generate Haskell data types for each schema (XSD for example), they will be technically different, but semantically and structurally identical in many cases.
The data is complex, includes references, and service components must process whole graph and produce also similar response (a component might just update a field, but might need to analyze whole graph to collect all required information, might call other services as well).
How can I represent ns1:address and ns2:adress as one polymorphic type that has country and street elements and application needs process them as identical, but keeps serialization context for writing response in correct format (one representation might encode them in single string while other might carry also superfluous complex data)?
How close can I get to writing mostly code that defines semantic equivalence of data, business logic and generate all else? What features in Haskell language or libraries should I evaluate as building blocks for potential solution?
An option is to create a data type for each schema and create a function to map them to a common data type. Process it as you wish. You don't need to create polymorphic types.
This approach is similar to Pandoc's: you get a bunch of readers to parse documents to a common document structure, then use writers to convert that common structure to a particular format.
You just need the libraries to read your complex input data (and write it back, if necessary). The rest is functions and data types.
If you are really handling graphs, you can look at the Data.Graph module.
It sounds like this is a problems that is well served by the Type Class infrastructure, and the Lens library.
Use a Type Class to define a standard and consistent high-level interface to the various implementations. Make sure that you focus on the operations you wish to perform, not on the underlying implementation or process.
Use Lenses and Prisms to reach into the underlying datatypes and return answers to queries, and modify values "in-place", without resorting to full serialisation/de-serialisation.

Fetching NSManagedObjects based on attributes in related objects with inheritance?

I have a fairly complex CoreData data model with entities inheriting from others and I'm getting an exception when executing a predicate. For example:
#"player.score > 1000";
Where:
Player (abstract)
- name
- tags -> Tag
LocalPlayer : Player
- score
- lives
VirtualPlayer : Player
- difficultyLevel
Tag : NSManagedObject
- name
- color
- player -> Player
I understand why, Tag has a relationship to Player, and score is an attribute on LocalPlayer, so it isn't valid since it isn't on other Player subclasses. But I really don't want lose the hierarchy of my data model.
Is there a way (subqueries, maybe?) to limit my predicate to only run against LocalPlayer objects in the Tag:player->Player releationship? Any suggestions?
Thanks.
If you are attempting to perform a fetch request using this predicate, it is not possible. The predicate is compiled to an SQL statement, and it is validated before sending to the backing database for execution. Interestingly, Core Data implements inheritance in a single, large table. So the SQL statement would actually not fail and return a correct result. But it is failed before execution by the Core Data predicate parser, which validates it against its model. To overcome this, consider promoting the score property to the abstract class Player. Perhaps, store it as an NSNumber, which would allow having a nil value to indicate irrelevance (in cases of VirtualPlayer objects).
You could also reverse your fetch request, fetching all local players with score of 1000, and then taking a list of all the tags:
NSSet* tags = [[moc executeFetchRequest:localPlayersRequest error:NULL] valueForKey:#"#distinctUnionOfSets.tags"];
Note however, that this is less optimal, and you may consider prefetching the tags relationship for quicker union of sets.
You should not have a predicate like this. From a conceptional standpoint, a Player is not guaranteed to have a score. Instead, you should set the entity of your request to LocalPlayer.
Even better, in my opinion, would be to avoid the inheritance complexity altogether. If the attributes list in your question is exhaustive, I would think that you had better simplify the model to just a Player entity to include all the attributes. You could even add a boolean isVirtual to make query filters easier.
Keep it simple and readable. You may "lose the hierarchy" but you will "gain simplicity".

this has the advanteages of the IQueryable?

If I dont' wrong, I can get the data from a database in to ways:
First with an IEnumerable:
myContext.MyTable.ToList();
With an IQeryable:
IQueryable<MyTable> query = myContext.Mytable;
I know that one of the advantages is that IQueryable execute the conditions in the server, so is more efficient and faster that IEnumerable.
But In my repository, as I return a List, I would like to know if this:
return query.ToList();
has the advantages of the IQueryable.
query.ToList() is the same like myContext.MyTable.ToList(). It returns a collection in memory (the whole database table) and is just an IEnumerable<T>, not an IQueryable<T>. Every further LINQ operator - for example a Where clause - you append, will be performed in memory and not in the database.
If you choose to return IEnumerable<T> or List<T> from your repository you have to design the repository methods so that you can apply filters, sorting, etc. inside of those methods - for example by passing in filter and sort expressions as parameters into the methods or by creating lots of specialized methods for different use cases - like GetOrdersByCustomerId, GetOrdersByShippingDate, etc., etc. If you do it outside of and after calling repository methods you will suffer from poor performance.

Resources