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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.