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

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.

Related

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".

Saving various core data entities of the same type with multiple different relationships?

I've been trying to debug this for 2 hours, have to sleep. First, I've searched and found many similar posts with they keywords: many entities same type and this one:
Core Data: inverse relationship for two relationships with same type
But to no avail. Here's what's happening:
I have a data model with two types. For example, I have a Person, and that person can have 4 lists of emails. The email type is its own thing, so I make the person store 4 distinct sets (relationships) to each list.
Basically, when I retrieve one set, it grabs all of them. All 4 lists are now 1, and it doesn't seem to matter how I set the inverses. Actually these changes somehow caused the entire thing to not save anything, all nil objects when downloaded. Previous to this, it worked fine (except for shoving all 4 lists into one set). All I updated was the data model for relationships. I may have exported the files in the wrong order, but do not know if that's related.
I simply can't find the keyword combination to find if someone's asked this before. I don't see how it wouldn't come up, what I'm doing is basic abstraction. I keep thinking I overlooked one box.
To summarize, I have a person, and person has 2 lists. I add them similar to this:
person.friendEmailsList = downloadedEmailsFromFriends;
person.businessEmailsList = downloadedBusinessEmails;
so later, I access person.friendEmailsList (using the correct core data call, of course), and instead of getting just friends, I get everything... friends, businesses everything
Any suggestions would be appreciated
There are two possible solutions.
First, you can use the approach you use. Just make sure that you also have corresponding reverse relationships from the other entity. So if you have 2 relationships to the same entity, that entity needs 2 distinct relationships back. E.g.
Person.friendsLists --->> List
Person.businessLists --->> List
List.friendPerson ---> Person
List.businessPerson ---> Person
The more flexible approach would be to have the list have an extra attribute type (could be a number as some kind of enum).
typedef enum {Friend = 1, Business } ListType;
You could put this into your List.h file. Now, to access just friend lists you can do this:
NSSet *friendList = [person.lists filteredSetUsingPredicate:
[NSPredicate predicateWithFormat:#"type = %#", #(Friend)]];
This might be a bit much to type, so you can simplify by putting an accessor method into your Person.m (declare it in .h):
-(NSSet*)friendsLists {
return [person.lists filteredSetUsingPredicate:
[NSPredicate predicateWithFormat:#"type = %#", #(Friend)]];
}
Now you can access the lists with the usual convenient person.friendsLists.

How do I access Core Data Attribute validation information from code?

I have a string attribute in a Core Data entity whose Max Length value is 40. I'd like to use this value in code and not have to re-type the value "40." Is this possible?
As #K.Steff says in the comments above, you are better off validating in your code and not setting a max length in your core data model. To add on to that comment, I would also advise you to look at using a custom NSManagedObject subclass for this entity type, and within that subclass overriding the validateValue:forKey:error: or implementing a key-specific validation method for this property.
The value of this approach is that you can do things like "coerce" the validation by truncating strings at validation time. From the NSManagedObject documentation:
This method is responsible for two things: coercing the value into an appropriate
type for the object, and validating it according to the object’s rules.
The default implementation provided by NSManagedObject consults the object’s entity
description to coerce the value and to check for basic errors, such as a null value when
that isn’t allowed and the length of strings when a field width is specified for the
attribute. It then searches for a method of the form validate< Key >:error: and invokes it
if it exists.
You can implement methods of the form validate< Key >:error: to perform validation that is
not possible using the constraints available in the property description. If it finds an
unacceptable value, your validation method should return NO and in error an NSError object
that describes the problem. For more details, see “Model Object Validation”. For
inter-property validation (to check for combinations of values that are invalid), see
validateForUpdate: and related methods.
So you can implement this method to both validate that the string is not too long and, if necessary, truncate it when it is too long.
From NSManagedObject you can access the NSEntityDescription via entity. In there you can grab the array properties and a dictionary propertiesByName, either of which will get you to NSPropertyDescriptions. Each property description has a property, validationPredicates that will return an array of NSPredicates. One of those will be the condition that your string length must be at most 40.
Sadly predicates are a lot of hassle to reverse engineer — and doing so can even be impossible, given that you can create one by supplying a block. Hopefully though you'll just have an NSComparisonPredicate or be able to get to one by tree walking downward from an NSCompoundPredicate or an NSExpression.
From the comparison predicate you'll be able to spot from the left and right expressions that one is string length and the other is a constant value.
So, in summary:
Core Data exposes validation criteria only via the very general means of predicates;
you can usually, but not always, rebuild an expression (in the natural language sense rather than the NSExpression sense) from a predicate; and
if you know specifically you're just looking for a length comparison somewhere then you can simplify that further into a tree walk for comparison predicates that involve the length.
It's definitely not going to be pretty because of the mismatch of the specific and the general but it is possible.

Entity Framework 4, SQLCe with POCO problem on delete

I have a SQLCe database which had a unique primary key Id with type uniqueidentifier, and child relationship, 1 to many, where i keep the master id in a column and append unique id for every row too. Now I use POCO entities for my domain model NOT STE. While adding and modifying entities works OK, I have hard time to delete, say for now individual child records, where of course supposed that they have they're own primary key. Soon as i give the deleted list and iterate through each entity while first entity is attached, in the second i get the exception:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
I should mention that i first make any add and modify entities to the database while opening a context...disposing and call another method for deletion where of course opens another context and if it ends successfully disposing.
Whats the meaning for this exception that I don't get?
This exception occurs when you have two different instances of the same entity in your object graph. This exception also occurs in STE but there is a work-around for that.
Basically, you have two entities (POCO), each with a relationship to a third entity. When you try to associate the first entity with the second and try to persist it into the Entity Context, both entities will have a seperate instance of the third and this is where the error is.
Work-around:
Before you make the association between two entities, try to "merge" any related entities together. This is so that the Entity Context does not need to make the decision of which instance of the "common entity" to persist.
Example:
A, (B1,B2), C are entities.
A -- B1
C -- B2
A -- B1 -- C
In this scenario, B1 and B2 are both B entities, just different instances (may be due to different calls to the data store through different contexts). When you want to associate A and C, you must choose to drop B2 and link C to B1.

Value vs Entity objects (Domain Driven Design)

I have just started reading DDD. I am unable to completely grasp the concept of Entity vs Value objects.. Can someone please explain the problems (maintainability, performance.. etc) a system could face when a Value object is designed as a Entity object? Example would be great...
Reduced to the essential distinction, identity matters for entities, but does not matter for value objects. For example, someone's Name is a value object. A Customer entity might be composed of a customer Name (value object), List<Order> OrderHistory (List of entities), and perhaps a default Address (typically a value object). The Customer Entity would have an ID, and each order would have an ID, but a Name should not; generally, within the object model anyway, the identity of an Address probably does not matter.
Value objects can typically be represented as immutable objects; changing one property of a value object essentially destroys the old object and creates a new one, because you're not as concerned with identity as with content. Properly, the Equals instance method on Name would return "true" as long as the object's properties are identical to the properties of another instance.
However, changing some attribute of an entity like Customer doesn't destroy the customer; a Customer entity is typically mutable. The identity remains the same (at least once the object has been persisted).
You probably create value objects without realizing it; anytime you are representing some aspect of an Entity by creating a fine-grained class, you've got a value object. For example, a class IPAddress, which has some constraints on valid values but is composed of simpler datatypes, would be a value object. An EmailAddress could be a string, or it could be a value object with its own set of behaviors.
It's quite possible that even items that have an identity in your database don't have an identity in your object model. But the simplest case is a composite of some attributes that make sense together. You probably don't want to have Customer.FirstName, Customer.LastName, Customer.MiddleInitial and Customer.Title when you can compose those together as Customer.Name; they'll probably be multiple fields in your database by the time you think about persistence, but your object model doesn't care.
Any object that is collectively defined by all of it attributes is a value object. If any of the attributes change you have a new instance of a value object. This is why value objects are defined as immutable.
If the object is not fully defined by all of its attributes then there are a subset of attributes that make up the identity of the object. The remaining attributes can change without redefining the object. This kind of object cannot be defined at immutable.
A simpler way of making the distinction is to think of value objects as static data that will never change and entities as data that evolves in your application.
Value Types :
Value types do not exist on his own, depends on Entity types.
Value Type object belongs to an Entity Type Object.
The lifespan of a value type instance is bounded by the lifespan of the owning entity instance.
Three Value types: Basic(primitive datatypes), Composite(Address) and Collection(Map, List, Arrays)
Entities:
Entity types can exist on his own (Identity)
An entity has its own life-cycle. It may exist independently of any other entity.
For example: Person, Organisation, College, Mobile, Home etc.. every object has its own identity
I don't know if the following is correct, but I would say that in the case of an Address object, we want to use it as a Value Object instead of an Entity because changes to the entity would be reflected on all linked objects (a Person for instance).
Take this case: You are living in your house with some other people. If we would use Entity for Address, I would argue that there would be one unique Address that all Person objects link to. If one person moves out, you want to update his address. If you would update the properties of the Address Entity, all people would have a different address. In the case of a Value Object, we would not be able to edit the Address (since it is immutable) and we would be forced to provide a new Address for that Person.
Does this sound right? I must say that I was/am also still confused about this difference, after reading the DDD book.
Going one step further, how would this be modelled in the database? Would you have all properties of the Address object as columns in the Person table or would you create a separate Address table that would also have a unique identifier? In the latter case, the people living in the same house would each have a different instance of an Address object, but those objects would be the same except for their ID property.
address can be entity or value object that depends on the busiess process. address object can be entity in courier service application but address can be value object in some other application. in courier application identity matters for address object
3 distinction between Entities and Value Objects
Identifier vs structural equality:
Entities have identifier,entities are the same if they have the same
identifier.
Value Objects on beyond the hand have structural equality, we consider two
value objects equal when all the fields are the same. Value objects cannot
have identifier.
Mutability vs immutability:
Value Objects are immutable data structures whereas entities change during
their life time.
Lifespan: Value Objects Should belong to Entities
In a very simple sentence I can say, we have three types of equality:
Identifier equality: a class has id filed and two objects are compared with their id field value.
Reference equality: if a reference to two objects has a same address in memory.
Structural equality: two objects are equal if all members of them are matched.
Identifier equality refers only to Entity and structural equality refers to Value Object only. In fact Value Objects do not have id and we can use them interchangeably. also value objects must be immutable and entities can be mutable and value objects will not have nay table in database.
I asked about this in another thread and I think I'm still confused. I may be confusing performance considerations with data modelling. In our Cataloging application, a Customer doesn't change until it needs to. That sounds dumb - but the 'reads' of customer data far outnumber the 'writes' and since many many web requests are all hitting on the 'active set' of objects, I don't want to keep loading Customers time and again. So I was headed down an immutable road for the Customer object - load it, cache it, and serve up the same one to the 99% of (multi-threaded) requests that want to see the Customer. Then, when a customer changes something, get an 'editor' to make a new Customer and invalidate the old one.
My concern is if many threads see the same customer object and it is mutable, then when one thread starts to change it mayhem ensues in the others.
My problems now are, 1) is this reasonable, and 2) how best to do this without duplicating a lot of code about the properties.
Consider the following examples from Wikipedia, in order to better understand the difference between Value Objects and Entities:
Value Object: When people exchange dollar bills, they generally do not
distinguish between each unique bill; they only are concerned about the face
value of the dollar bill. In this context, dollar bills are Value Objects. However,
the Federal Reserve may be concerned about each unique bill; in this context each
bill would be an entity.
Entity: Most airlines distinguish each seat uniquely on every flight. Each seat is
an entity in this context. However, Southwest Airlines, EasyJet and Ryanair do
not distinguish between every seat; all seats are the same. In this context, a seat is
actually a Value Object.

Resources