Re: Multithreading EOAccess
Carl Lindberg <[email protected]>
| Newsgroups | gmane.comp.web.webobjects.eof |
|---|---|
| Message-ID | <[email protected]> |
Modifying the EOModel should normally be OK if you lock the
EODatabaseContext while you're doing it, at least if there is only one
EODatabaseContext per EOModel (the usual case). However, if you have
multiple EOObjectStoreCoordinators using the same EOModelGroup, then I
guess this approach isn't quite enough any more.
You could always go back to the older way of doing things, going down
through EOAccess layers. That approach should be threadsafe in that it
does not modify the EOModel, but it's uglier code :-)
This is some old ObjC code I had lying around to do this. It would
have to be ported to the 5.x Java, which means dealing with expression
factories instead of expression classes, plus adding any necessary
lock/unlock calls to the appropriate EOAccess objects, but I think it
can be done.
@implementation EOEditingContext (extras)
- (unsigned)rowCountForEntityNamed:(NSString *)name
qualifier:(EOQualifier *)qualifier
{
EOEntity *entity = [self entityNamed:name];
NSString *modelName = [[entity model] name];
EOFetchSpecification *spec;
EODatabaseContext *databaseContext = [self
databaseContextForModelNamed:modelName];
EOAdaptorContext *adaptorContext = [databaseContext
adaptorContext];
Class expressionClass = [[adaptorContext adaptor]
expressionClass];
EOQualifier *schemaQualifier;
EOSQLExpression *dummyExpression;
EOSQLExpression *countExpression;
NSMutableString *sqlString;
NSEnumerator *bindingEnum;
NSMutableDictionary *binding;
NSArray *results;
id <EOQualifierSQLGeneration> sqlQualifier = qualifier;
schemaQualifier = [sqlQualifier
schemaBasedQualifierWithRootEntity:entity];
spec = [EOFetchSpecification fetchSpecificationWithEntityName:name
qualifier:schemaQualifier sortOrderings:nil];
dummyExpression = [expressionClass
selectStatementForAttributes:[entity primaryKeyAttributes]
lock:NO fetchSpecification:spec entity:entity];
sqlString = [NSMutableString stringWithFormat:@"SELECT COUNT(*)
FROM %@",
[dummyExpression tableListWithRootEntity:entity]];
if (schemaQualifier)
[sqlString appendFormat:@" WHERE %@", [dummyExpression
whereClauseString]];
countExpression = [expressionClass expressionForString:sqlString];
bindingEnum = [[dummyExpression bindVariableDictionaries]
objectEnumerator];
while (binding = [bindingEnum nextObject])
[countExpression addBindVariableDictionary:binding];
results = [self rawRowsWithExpression:countExpression
modelNamed:modelName];
if(results != nil && [results count] > 0) {
// The results should be a dictionary with one key and object.
return [[[[results lastObject] allValues] lastObject]
unsignedIntValue];
}
return 0;
}
/*"
* Similar to -#rawRowsWithSQL:modelNamed:, but this method takes a raw
* EOSQLExpression. Mainly for use by other EOEditingContext methods
rather
* than being called directly.
"*/
- (NSArray *)rawRowsWithExpression:(EOSQLExpression *)expression
modelNamed:(NSString *)name
{
EODatabaseContext *databaseContext = [self
databaseContextForModelNamed:name];
EODatabaseChannel *databaseChannel = [databaseContext
availableChannel];
EOAdaptorChannel *adaptorChannel = [databaseChannel
adaptorChannel];
NSMutableArray *results;
NSDictionary *row;
if ( ![adaptorChannel isOpen] ) {
[adaptorChannel openChannel];
}
[adaptorChannel evaluateExpression:expression];
[adaptorChannel setAttributesToFetch:[adaptorChannel
describeResults]];
results = [NSMutableArray array];
while ( (row = [adaptorChannel fetchRowWithZone:[self zone]]) ) {
[results addObject:row];
}
return results;
}
@end