Search code examples
ioscore-datansfetchrequest

Core Data Queries


I am still trying to wrap my head around Core Data and am having trouble letting go of SQL. I know that they are not the same but I am finding it hard to recreate what I can do in SQL. I am hoping someone can help.

What I want to do is create a list of Clients and return a sum of their current bill. I have two entities:

Client

  • name
  • address
  • etc

Billing

  • Client
  • date
  • amount
  • etc

I have created a one-to-many relationship between the 2 entities and have my NSEntityDescription pointing to Client.

Now what I want to happen in SQL terms is this:

SELECT *, SUM(amount) as Total FROM Clients INNER JOIN Billing......"

  • Can this be done with one Fetch Request or would I do 2 Requests and then merge them?
  • Can I somehow use valueForKey:@"[email protected]"?

  • Also could anyone recommend a great Core Data book (or website) for beginners, intermediate level?


Solution

  • Can this be done with one Fetch Request or would I do 2 Requests and then merge them?

    Yes it can be done with one request. see here

    /*UNTESTED*/
    - (NSNumber*) billingSumForClient:(NSManagedObjectID*)clientId
                               context:(NSManagedObjectContext*)context
    {
        NSNumber* total = nil;
        NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Billing"];
        [request setResultType:NSDictionaryResultType];
        NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"amount"];
        NSExpression *sumExpression = [NSExpression expressionForFunction:@"sum:"
                                                                arguments:[NSArray arrayWithObject:keyPathExpression]];
        NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
        [expressionDescription setName:@"total"];
        [expressionDescription setExpression:sumExpression];
        [expressionDescription setExpressionResultType:NSDateAttributeType];
        [request setPredicate:[NSPredicate predicateWithFormat:@"client == %@",clientId]];
        [request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
        NSError *error = nil;
        NSArray *objects = [context executeFetchRequest:request error:&error];
        if (&error) {
            // Handle the error.
        } else {
            if ([objects count] > 0) {
                total = [[objects objectAtIndex:0] valueForKey:@"total"];
            }
        }
        return total;
    }
    

    Can I somehow use valueForKey:@"[email protected]"?

    Yes. see here(@Daniel link)
    This might be faster if all your billings are already faulted into your current context.