Group by Core Data gives error - core-data

I am trying to fetch a request and I want to group by "Premium Accounts" and fetch the card number, card holder name and stuff like that. I am getting a weird error -
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'SELECT clauses in queries with GROUP BY components can only contain properties named in the GROUP BY or aggregate functions ((), name gCardHolderName, isOptional 1, isTransient 0, entity Merchant, renamingIdentifier gCardHolderName, validation predicates (
), warnings (
), versionHashModifier (null)
userInfo {
}, attributeType 700 , attributeValueClassName NSString, defaultValue (null) is not in the GROUP BY)'
I assume that's the SQL query - SELECT CARDHOLDERNAME, PREMIUM ACCOUNT NAME FROM "MERCHANT" GROUP BY PREMIUM ACCOUNT NAME.
Premium account name can be the same (for account 1, I can have different card holder names).
I have no clue about this error. Here' my code if anybody can help me out -
pragma mark - FetchRequest Method
- (void)fetchRequest
{
NSError * anyError = nil;
AppDelegate * applicationDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = [applicationDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Merchant" inManagedObjectContext:context];
[request setEntity:entity];
[request setFetchBatchSize:15];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"premiumActName" ascending:NO];
NSArray *descriptors = [NSArray arrayWithObjects:sortDescriptor1, nil];
[request setSortDescriptors:descriptors];
NSPropertyDescription *accountDesc = [[entity propertiesByName] objectForKey:#"premiumActName"];
NSPropertyDescription *cardHolderDesc = [[entity propertiesByName] objectForKey:#"gCardHolderName"];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: #"premiumActName"];
NSExpression *countExpression = [NSExpression expressionForFunction: #"count:"
arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: #"count"];
[expressionDescription setExpression: countExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];
NSArray *propertiesToFetch= #[accountDesc,cardHolderDesc, expressionDescription];
[request setPropertiesToFetch:propertiesToFetch];
[request setPropertiesToGroupBy:[NSArray arrayWithObject:#"premiumActName"]];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[context save:&anyError];
NSArray * distinctResults = [context executeFetchRequest:request error:&anyError];
[distinctResults enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
NSLog(#" objects=%#", [dict objectForKey:#"gCardHolderName"]);
}];
if(_fetchedResultsController)
{
_fetchedResultsController = nil;
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
if(![_fetchedResultsController performFetch:&anyError])
{
NSLog(#"error fetching:%#", anyError);
}
[self.membersTblView reloadData];
}

[request setPropertiesToGroupBy:propertiesToFetch]

Related

iOS Core Data error when updating

I want to update a field in a table. However when I save after fetching and modifying the field, error 1570 is thrown. [Mandatory value is nil].
MyAppDelegate *appdelegate = DELEGATE;
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyTable" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(myAttribute_id = %#)",myAttribute.attribute_id];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
for (myAttribute *obj in results) {
NSLog(#"myAttribute_id : %#",myAttribute.attribute_id);
[obj setValue:myAttribute.attribute2_id forKey:#"attribute2_id"];
[context save:&error];
NSLog(#"save error : %#",error);
}
Here I get an error. Whereas all mandatory fields are already set.

Core Data Sort Descriptors with relationships between Entities

I have two entities, Job and Client. The relationship from job to client is called clientOfJob which is a many-to-one relationship:
Job<<-->Client
I am trying to understand how I would sort my fetch results into sections for the table view, with the sections based on client first names.
This is my first attempt to use sectionNameForKeyPath, but I am using sample code from CoreDataBooks, and so far, substituting some of that code has eliminated some serious problems I had earlier today.
Here is the code I tried. I didn't think it would work, but I'm not sure what I need to use for the client sort descriptor key and for the sectionNameKeyPath.
By the way, the code works well with only the jobSortDescriptor (without the clientSortDescriptor) and with sectionNameKeyPath set to nil. Then it just sorts by job description. I can get at the related client entity information, putting client name information into the detailedTextLabel of each cell while I have the job description in the textLabel of the cell.
- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:10];
NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"clientOfJob.firstName" ascending:YES];
NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"jobDescription" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:dataInterface.managedObjectContext sectionNameKeyPath:#"clientOfJob.firstName" cacheName:#"Jobs"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[jobSortDescriptor release];
[clientSortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved Error %#, %#", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}

(Core Data )Fetch an specific entity with a max property

I have a Entity wich has a toMany relationship to another one. In this second one I have an attribute called "versionNumber" so. I have an object on entity type A, and I want to get the related entity B which has the biggest (max) versionNumber.
I have the following but that returns me a result obtained over all records on entity B, not over the specific entities related to the object of type A.
NSInteger vNumber = 0;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:DPA_VERSION_KEY inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];
// Specify that the request should return dictionaries.
[request setResultType:NSDictionaryResultType];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:VERSION_NUMBER_KEY];
NSExpression *maxNumberExpression = [NSExpression expressionForFunction:#"max:"
arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"maxNumber"];
[expressionDescription setExpression:maxNumberExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
// Execute the fetch.
NSError *error = nil;
NSArray *objects = [[self managedObjectContext] executeFetchRequest:request error:&error];
if (objects == nil) {
// Handle the error.
}
else {
if ([objects count] > 0) {
vNumber = [[[objects objectAtIndex:0] valueForKey:#"maxNumber"] integerValue] +1;
}
}
[expressionDescription release];
[request release];
return vNumber;
I have an idea but I hadn't been able to materialize it. I must ask SELF which is my object A to do that fetch over its relationship toVersions (Entity B).
Thanks for the help.
G.
Set a predicate to limit the request to only those B objects who have a relationship with A.
[request setPredicate:[NSPredicate predicateWithFormat:#"myA == %#", myA];

Printing Core Data

I'm working on a program and I have created a fetch request to grab the data that I need to print. I'm able to log information like this:
2010-10-03 16:57:10.362 lzshow7.2[2537:10b] <NSManagedObject: 0x2ca120> (entity: Song; id: 0x2afcb0 <x-coredata://CF5A85CE-BE0F-4ADC-979A-7F4214A8FB19/Song/p9> ; data: {
cueName = Freedom;
cueNo = 014;
cueNotes = nil;
songToInstrument = "<relationship fault: 0x2b1800 'songToInstrument'>";
})
How do I seperate the properties like cueName, cueNo, cueNotes out to be printed?
Here is the fetch request:
//Managed object context???
NSLog(#"setting Managed object stuff");
NSManagedObjectContext *context=[[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];
NSLog(#"Second line of Managed object stuff");
//fetch request:
NSLog(#"Starting to fetch:");
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Song" inManagedObjectContext:context];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"cueNo" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error;
NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
for (id obj in mutableFetchResults)
NSLog(#"%#", obj);
NSLog(#"finished looping");
//Error handling
if (mutableFetchResults == nil) {
// Handle the error.
}
//[self setEventsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
}
Any help would be greatly appreciated.
Thank you,
Loren
You use basically the opposite of how you stored the values in your managedObject
NSString *name = [song valueForKey:#"cueName"];
NSNumber *number = [song valueForKey:#"cueNo"];
NSString *notes = [song valueForKey:#"cueNotes"];
...
NSLog(#"%# %# %#", name, number, notes);
if you've created a custom Class of your entity you could add this method:
- (NSString *)description {
NSString *name = [song valueForKey:#"cueName"];
NSNumber *number = [song valueForKey:#"cueNo"];
NSString *notes = [song valueForKey:#"cueNotes"];
...
NSString *returnString = [NSString stringWithFormat:#"%# %# %#", name, number, notes];
return returnString;
}
With this method you can just use NSLog(#"%#", object); to get a nice formatted output

Coredata for getting all the values of a field

I have an entity ("Settings") and I want to get all the values in just one field ("Status").I am using coredata. Can anyone help me, please?
Declare this in .h file:
NSMutableArray *eventArray;
and in .m file
- (void)fetchRecords {
// Setup the fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Settings" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Status" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
[fetchRequest setEntity:entity];
NSError *error;
// Get array of results.
NSMutableArray *theResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (!theResults) {
// Handle the error.
// This is a serious error and should advise the user to restart the application
}
// Grab unique neighborhoods through NSSet.
NSSet *uniqueElements = [NSSet setWithArray:[theResults valueForKey:#"Status"]];
// Dump NSSet uniques into new array.
NSMutableArray *sortedResults = [[NSMutableArray alloc] initWithArray:[uniqueElements allObjects]];
for(int i = 0; i < [sortedResults count];i++)
{
NSLog(#"%d. %#", i+1, [sortedResults objectAtIndex:i]);
}
// Save our fetched data to an array
[self setEventArray: sortedResults];
}
At first, u can get Array of values:
NSFetchRequest *requestSettings = [[NSFetchRequest alloc] init];
[requestCodesList setEntity:[NSEntityDescription entityForName:#"Setting" inManagedObjectContext:managedObjectContext]];
NSArray *setting = [managedObjectContext executeFetchRequest:requestCodesList error:&error];
if (error) NSLog(#"Failed to executeFetchRequest to data store: %#", [error localizedDescription]);
Next, u transfer u array in NSString:
ComponentsJoinedByString: Constructs
and returns an NSString object that is
the result of interposing a given
separator between the elements of the
array.
(NSString *)componentsJoinedByString:(NSString *)separator
code is:
NSString *settingChanged = [setting componentsJoinedByString:#","];
And after u can using this anywhere in u UI (binding, setStringValue e.t.c)

Resources