FROM : Marcus S. Zarra
DATE : Fri May 04 23:08:03 2007
Interesting that your example causes the faults to fire. By removing
the bindings from the equation I was not able to duplicate your
results.
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:@"Invoice"
inManagedObjectContext:managedObjectContext]];
[request setPredicate:[NSPredicate predicateWithFormat:@"invoiceNumber == 19"]];
NSError *errord;
NSArray *array = [managedObjectContext executeFetchRequest:request
error:&errord];
if (!array) {
NSLog(@"Error: %@", errord);
return;
}
NSLog(@"Count of invoices: %d\n%@", [array count], array);
id invoice = [array objectAtIndex:0];
id detailSet = [invoice valueForKey:@"invoiceDetails"];
NSLog(@"Count of details: %d\n%@", [detailSet count], detailSet);
--------Output
2007-05-04 14:44:15.634 seSales[25169] Count of invoices: 1
(
<InvoiceEntity: 0x4e82c0> (entity: Invoice; id: 0x5d37860
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/Invoice/p334> ;
data: <fault>)
)
2007-05-04 14:44:15.650 seSales[25169] Count of details: 5
<_NSFaultingMutableSet: 0x5b33930> (<InvoiceDetailEntity: 0x5d9efb0>
(entity: InvoiceDetail; id: 0x4f1da0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p1230>
; data: <fault>), <InvoiceDetailEntity: 0x4ce240> (entity:
InvoiceDetail; id: 0x4f1dc0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p2140>
; data: <fault>), <InvoiceDetailEntity: 0x5d29320> (entity:
InvoiceDetail; id: 0x4f1d50
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p1210>
; data: <fault>), <InvoiceDetailEntity: 0x4cd2b0> (entity:
InvoiceDetail; id: 0x4f1de0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p2217>
; data: <fault>), <InvoiceDetailEntity: 0x4ce200> (entity:
InvoiceDetail; id: 0x5d9e190
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p452>
; data: <fault>))
As you can see I am accessing the invoiceDetails through the
relationship and in my output I do not get the items fired. So this
may indicate that the array controller is giving you a proxy object in
your example or some other magic is going on behind the scenes.
NOTE: the OP was looking for a way to perform a "select count(*) from
xxx" which the above code does perform without a performance hit of
firing the faults.
Marcus S. Zarra
Zarra Studios LLC
Simply Elegant Software for OS X
www.zarrastudios.com
On 5/4/07, Robert Walker <<email_removed>> wrote:
> Marcus,
>
> Ok for my own sanity and full understanding of this, I created a very
> simple Core Data application with a button connected to an action
> used to count people in a department:
>
> Here's my counting code:
>
> 01 (IBAction)countPeople:sender
> 02 {
> 03 NSManagedObject *selection = [[arrayController selectedObjects]
> objectAtIndex:0];
> 04 NSLog(@"\n\nDepartment before counting: %@", [selection
> description]);
> 05
> 06 int count = [[selection valueForKey:@"people"] count];
> 07
> 08 NSLog(@"\n\nCount of people: %d", count);
> 09 NSLog(@"\n\nDepartment after counting: %@", [selection
> description]);
> 10 }
>
> And here are the results:
>
> [Session started at 2007-05-04 15:55:51 -0400.]
> 2007-05-04 15:55:56.931 FaultTest[3015]
>
> Department before counting: <NSManagedObject: 0x320b00> (entity:
> Department; id: 0x320dd0 <x-coredata://9C7E671E-A376-4ED1-AB42-
> AC0F88013CE6/Department/p1> ; data: {name = "Department A"; people =
> "<relationship fault: 0x320ff0 'people'>"; })
> 2007-05-04 15:55:56.933 FaultTest[3015]
>
> Count of people: 2
> 2007-05-04 15:55:56.934 FaultTest[3015]
>
> Department after counting: <NSManagedObject: 0x320b00> (entity:
> Department; id: 0x320dd0 <x-coredata://9C7E671E-A376-4ED1-AB42-
> AC0F88013CE6/Department/p1> ; data: {
> name = "Department A";
> people = (
> 0x31b2f0 <x-coredata://9C7E671E-A376-4ED1-AB42-AC0F88013CE6/
> Person/p4>,
> 0x31c250 <x-coredata://9C7E671E-A376-4ED1-AB42-AC0F88013CE6/
> Person/p1>
> );
> })
>
> Does this not indicate that accessing the count of people, through
> the relationship on a department, does indeed fire the fault? Or is
> there another way of getting the count without using KVC to access
> the "people" relationship on a department (as shown in line 6)?
>
> On May 4, 2007, at 1:03 PM, Marcus S. Zarra wrote:
>
> > Basically, the fetch will return an array of faults if the objects are
> > not already in memory. Performing a count on the array will not cause
> > the faults to fire since you are not accessing the attributes of the
> > objects inside of the array. You are just asking the array how many
> > objects it holds.
> >
> > Personally, I would recommend this method over keeping a count
> > attribute in a parent object. It is way too easy for that count to
> > get out of sync with the array. Since counting the number objects in
> > the relationship will not cause the faults to fire it is safer to get
> > this information each time it is requested.
> >
> > Marcus S. Zarra
> > Zarra Studios LLC
> > Simply Elegant Software for OS X
> > www.zarrastudios.com
> >
> >
> > On 5/4/07, Robert Walker <<email_removed>> wrote:
> >> Marcus,
> >>
> >> > Again no. Fortunately when the array is retrieved all of the
> >> objects
> >> > are "faults" which means they are not loaded into memory yet and
> >> your
> >> > call to count will not cause them to load. Therefore the memory
> >> and
> >> > performance hits are negligible.
> >>
> >> Are you sure that asking for the count would not cause the fault
> >> representing a collection to fire? If so that's really impressive.
> >> How would Core Data know the number of objects represented by the
> >> fault without realizing the fault first?
> >>
> >> --
> >> Robert Walker
> >> <email_removed>
> >>
> >>
DATE : Fri May 04 23:08:03 2007
Interesting that your example causes the faults to fire. By removing
the bindings from the equation I was not able to duplicate your
results.
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:@"Invoice"
inManagedObjectContext:managedObjectContext]];
[request setPredicate:[NSPredicate predicateWithFormat:@"invoiceNumber == 19"]];
NSError *errord;
NSArray *array = [managedObjectContext executeFetchRequest:request
error:&errord];
if (!array) {
NSLog(@"Error: %@", errord);
return;
}
NSLog(@"Count of invoices: %d\n%@", [array count], array);
id invoice = [array objectAtIndex:0];
id detailSet = [invoice valueForKey:@"invoiceDetails"];
NSLog(@"Count of details: %d\n%@", [detailSet count], detailSet);
--------Output
2007-05-04 14:44:15.634 seSales[25169] Count of invoices: 1
(
<InvoiceEntity: 0x4e82c0> (entity: Invoice; id: 0x5d37860
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/Invoice/p334> ;
data: <fault>)
)
2007-05-04 14:44:15.650 seSales[25169] Count of details: 5
<_NSFaultingMutableSet: 0x5b33930> (<InvoiceDetailEntity: 0x5d9efb0>
(entity: InvoiceDetail; id: 0x4f1da0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p1230>
; data: <fault>), <InvoiceDetailEntity: 0x4ce240> (entity:
InvoiceDetail; id: 0x4f1dc0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p2140>
; data: <fault>), <InvoiceDetailEntity: 0x5d29320> (entity:
InvoiceDetail; id: 0x4f1d50
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p1210>
; data: <fault>), <InvoiceDetailEntity: 0x4cd2b0> (entity:
InvoiceDetail; id: 0x4f1de0
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p2217>
; data: <fault>), <InvoiceDetailEntity: 0x4ce200> (entity:
InvoiceDetail; id: 0x5d9e190
<x-coredata://799303D2-FFF6-409B-BA4A-396CE56E3864/InvoiceDetail/p452>
; data: <fault>))
As you can see I am accessing the invoiceDetails through the
relationship and in my output I do not get the items fired. So this
may indicate that the array controller is giving you a proxy object in
your example or some other magic is going on behind the scenes.
NOTE: the OP was looking for a way to perform a "select count(*) from
xxx" which the above code does perform without a performance hit of
firing the faults.
Marcus S. Zarra
Zarra Studios LLC
Simply Elegant Software for OS X
www.zarrastudios.com
On 5/4/07, Robert Walker <<email_removed>> wrote:
> Marcus,
>
> Ok for my own sanity and full understanding of this, I created a very
> simple Core Data application with a button connected to an action
> used to count people in a department:
>
> Here's my counting code:
>
> 01 (IBAction)countPeople:sender
> 02 {
> 03 NSManagedObject *selection = [[arrayController selectedObjects]
> objectAtIndex:0];
> 04 NSLog(@"\n\nDepartment before counting: %@", [selection
> description]);
> 05
> 06 int count = [[selection valueForKey:@"people"] count];
> 07
> 08 NSLog(@"\n\nCount of people: %d", count);
> 09 NSLog(@"\n\nDepartment after counting: %@", [selection
> description]);
> 10 }
>
> And here are the results:
>
> [Session started at 2007-05-04 15:55:51 -0400.]
> 2007-05-04 15:55:56.931 FaultTest[3015]
>
> Department before counting: <NSManagedObject: 0x320b00> (entity:
> Department; id: 0x320dd0 <x-coredata://9C7E671E-A376-4ED1-AB42-
> AC0F88013CE6/Department/p1> ; data: {name = "Department A"; people =
> "<relationship fault: 0x320ff0 'people'>"; })
> 2007-05-04 15:55:56.933 FaultTest[3015]
>
> Count of people: 2
> 2007-05-04 15:55:56.934 FaultTest[3015]
>
> Department after counting: <NSManagedObject: 0x320b00> (entity:
> Department; id: 0x320dd0 <x-coredata://9C7E671E-A376-4ED1-AB42-
> AC0F88013CE6/Department/p1> ; data: {
> name = "Department A";
> people = (
> 0x31b2f0 <x-coredata://9C7E671E-A376-4ED1-AB42-AC0F88013CE6/
> Person/p4>,
> 0x31c250 <x-coredata://9C7E671E-A376-4ED1-AB42-AC0F88013CE6/
> Person/p1>
> );
> })
>
> Does this not indicate that accessing the count of people, through
> the relationship on a department, does indeed fire the fault? Or is
> there another way of getting the count without using KVC to access
> the "people" relationship on a department (as shown in line 6)?
>
> On May 4, 2007, at 1:03 PM, Marcus S. Zarra wrote:
>
> > Basically, the fetch will return an array of faults if the objects are
> > not already in memory. Performing a count on the array will not cause
> > the faults to fire since you are not accessing the attributes of the
> > objects inside of the array. You are just asking the array how many
> > objects it holds.
> >
> > Personally, I would recommend this method over keeping a count
> > attribute in a parent object. It is way too easy for that count to
> > get out of sync with the array. Since counting the number objects in
> > the relationship will not cause the faults to fire it is safer to get
> > this information each time it is requested.
> >
> > Marcus S. Zarra
> > Zarra Studios LLC
> > Simply Elegant Software for OS X
> > www.zarrastudios.com
> >
> >
> > On 5/4/07, Robert Walker <<email_removed>> wrote:
> >> Marcus,
> >>
> >> > Again no. Fortunately when the array is retrieved all of the
> >> objects
> >> > are "faults" which means they are not loaded into memory yet and
> >> your
> >> > call to count will not cause them to load. Therefore the memory
> >> and
> >> > performance hits are negligible.
> >>
> >> Are you sure that asking for the count would not cause the fault
> >> representing a collection to fire? If so that's really impressive.
> >> How would Core Data know the number of objects represented by the
> >> fault without realizing the fault first?
> >>
> >> --
> >> Robert Walker
> >> <email_removed>
> >>
> >>
| Related mails | Author | Date |
|---|---|---|
| Hell's KItchen Hel… | May 4, 13:25 | |
| Marcus S. Zarra | May 4, 18:45 | |
| Robert Walker | May 4, 18:47 | |
| Robert Walker | May 4, 18:59 | |
| Marcus S. Zarra | May 4, 19:03 | |
| Robert Walker | May 4, 22:04 | |
| Marcus S. Zarra | May 4, 23:08 | |
| Robert Walker | May 4, 23:48 | |
| Steve Israelson | May 5, 00:33 |






Cocoa mail archive

