HardikDabhi
HardikDabhi

Reputation: 2952

How to fetch Specific Data in One to Many Core Data Relationships?

I have made one sample demo on core data relationships.I have one Table "User" which is connected another table "Account" In form of "One to Many" relation.

Code

-(IBAction)savePersonData:(id)sender
{

    NSManagedObjectContext *context = appDelegate.managedObjectContext;

    NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
    [newDevice setValue:self.personName.text forKey:@"name"];
    [newDevice setValue:self.personAddress.text forKey:@"address"];
    [newDevice setValue:self.personMobileNo.text forKey:@"mobile_no"];


    NSManagedObject *newAccount = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:context];
    [newAccount setValue:self.accountNo.text forKey:@"acc_no"];
    [newAccount setValue:self.accountType.text forKey:@"acc_type"];
    [newAccount setValue:self.balance.text forKey:@"balance"];

    NSLog(@"Saved Successfully");
    [self dismissViewControllerAnimated:YES completion:nil];

}

Image is

My Question is

I have find so many time but could not find proper answer.So I post this question second time.

My question is I have insert Manually Three person With their Account's Details.

Now ,I Want A balance which I have entered for specific person when I enter Mobile number.

Ex

1)Enter 1st Mobile Num. Should be display first Person's Balance. 2)Enter 2nd Mobile Num. Should be display second Person's Balance. 1)Enter 3rd Mobile Num. Should be display third Person's Balance.

Balance Check Code

-(IBAction)checkBalance:(id)sender

{ NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"mobile_no = %@",self.textField.text];

    [fetchRequest setPredicate:predicate];
    NSError *error;
    NSArray *result = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    if(!([result count] == 0))
    {        

        NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
        NSFetchRequest *newFetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Account"];
        NSMutableArray *temp = [[managedObjectContext executeFetchRequest:newFetchRequest error:nil] mutableCopy];

        for (NSManagedObject *object in temp)
        {
            NSString *intValue = [object valueForKey:@"balance"];
            NSString *alertString = [NSString stringWithFormat:@"%@",intValue];
            [self displayAlertView:@"Available Balance" withMessage:alertString];
        }
    }
    else
    {
        [self displayAlertView:@"Error" withMessage:@"Please Enter Valid Mobile Number That you have entered in Bank"];
    }
}

Images

enter image description here

Output

enter image description here enter image description here

I want Balance With Specific Person Which I enter Person Mobile No on TextField.

Sorry Guys,I have asked second time ,But Could no able to solve this core data relationships.

Thank you.

Upvotes: 0

Views: 1722

Answers (1)

pbasdf
pbasdf

Reputation: 21536

First...

Fix the naming of your relationships. As others have pointed out in comments on your other question, you have named them back to front: in the Person entity, the to-many relationship to Account should be named "accounts" not "person". Likewise in the Account entity, the to-one relationship to Person should be named "person" not "accounts".

Next...

Although you have defined the "accounts" relationship as to-many, the savePersonData code in this question creates only one Account and one Person - but does not then set the relationship between them. (You can see this in your Output: each Account has nil for its "accounts" relationship).

The code in your previous question did set the relationship (by adding the newAccount to the relationship on the newPerson object). In your code above you could use (after fixing the relationship names):

NSMutableSet *setContainer = [newDevice mutableSetValueForKey:@"accounts"];
[setContainer addObject:newAccount];

but with one-many relationships it is easier to set the inverse relationship:

[newAccount setValue:newDevice forKey:@"person"];

Next...

Your checkBalance method correctly fetches any Person objects whose "mobile_no" attribute matches. But your subsequent code then fetches ALL Account objects - even if you had correctly set the relationship.

If you want only those Account objects that are related to a given Person, that is precisely what the "accounts" relationship represents. So you could just use that relationship to access the related Account objects:

if(!([result count] == 0)) {
    NSManagedObject *requiredPerson = (NSManagedObject *)result[0];
    NSSet *temp = [requiredPerson valueForKey:@"accounts"];
    for (NSManagedObject *object in temp) {
        NSString *intValue = [object valueForKey:@"balance"];
        NSString *alertString = [NSString stringWithFormat:@"%@",intValue];
        [self displayAlertView:@"Available Balance" withMessage:alertString];
    }
}

Alternatively, fetch the relevant Account objects directly (without fetching the Person object first) by specifying a predicate that traverses the relationship:

NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *newFetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Account"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person.mobile_no = %@",self.textField.text];
[newFetchRequest setPredicate:predicate];

NSMutableArray *temp = [[managedObjectContext executeFetchRequest:newFetchRequest error:nil] mutableCopy];

    for (NSManagedObject *object in temp)
    {
        NSString *intValue = [object valueForKey:@"balance"];
        NSString *alertString = [NSString stringWithFormat:@"%@",intValue];
        [self displayAlertView:@"Available Balance" withMessage:alertString];
    }

Upvotes: 2

Related Questions