Enterprise Objects Framework Release 2.2. Copyright (C)1997 by Apple Computer, Inc. All Rights Reserved. Release Notes: Enterprise Objects Framework 2.2 This document contains the release notes for release 2.2 of Enterprise Objects Framework, included with release 3.5 of WebObjects. Information about the release discovered since manufacture is continually being incorporated into the release notes, the most current version of which is posted on the Web at http://ent.apple.com/NeXTanswers/HTMLFiles/2455.htmld/2455.html. The Windows version of this release can be used to develop software for Intel machines running Windows NT. The MachOS version of this release is 3-way fat; it can be used to develop software for NeXT, Intel, and SPARC. The PDO version of this release can be used to develop software for Solaris and HPUX. None of the versions have been qualified for OpenStep application development. Note that the installation of WebObjects 3.5 replaces your existing OpenStep installation with new development tools, frameworks, and files. For example, there are modificiations to ProjectBuilder, makefiles, and project types to accomodate new features in WebObjects. Interface Builder and the AppKit framework are installed with WebObjects 3.5, but have not updated from the OPENSTEP 4.2 release. While we don't believe there are problems developing OpenStep applications on a WebObjects 3.5 system, you will not receive support related to problems you encounter while developing OpenStep-based applications. If you need to develop OpenStep applications on a supported platform, use a machine that does not have WebObjects 3.5 installed. These release notes are organized into the following sections: * Information About Other Releases * Notes specific to Windows NT Developers * Notes specific to PDO Developers * Database Client Libraries * New Features in Release 2.2 * Locating the Documentation for this Release * Installing the Examples * Known Problems in Release 2.2 * Enterprise Objects Framework User Defaults Note: Because release 2.0 of Enterprise Objects Framework and later releases are based on the same architecture, many of the subjects in this document are relevant to all 2.x releases. Consequently, the term "release 2.x" is used where a discussion applies equally to releases 2.0 and higher. Information About Other Releases This document describes the features introduced, the bugs fixed, and the known problems in Enterprise Objects Framework release 2.2. For a description of the features introduced in Enterprise Objects Framework release 2.0, see the 2.0 release notes. They contain a lot of information that's still relevant for 2.2, including information about converting release 1.x applications to 2.0 and a list of features shared with Enterprise Objects Framework release 1.2. The 2.0 release notes are available on the Web at http://ent.apple.com/NeXTanswers/HTMLFiles/2455.htmld/2455.html. For a description of how Enterprise Objects Framework 2.x differs from the preceding releases, see the document Differences Between Enterprise Objects Framework 1x and 2.0 in /NextLibrary/Documentation/NextDev/EnterpriseObjects/1x_To_2. Notes Specific to Windows NT Developers References to filenames in this document use UNIX format. On Windows NT, you can interpret these by reading backslashes for the slashes and adding the installation directory (c:\NeXT\ by default) to the beginning. For example, /NextLibrary/Documentation on Windows NT is c:\NeXT\NextLibrary\Documentation. To use Enterprise Objects Framework on Windows NT, you must have the appropriate database client libraries. The Sybase client libraries are provided on the WebObjects Enterprise 4.2 CD as an optional package. To install the Sybase client libraries, you must do a custom installation and explicitly specify that you want to install the package. To use Enterprise Objects Framework with Oracle or Informix, you must purchase the appropriate client libraries from your database vendor. Here's what you need: Oracle Phone: (800) 542-1170 or call your local sales representative Ask for: SQLNET v2.2 for PC/Windows NT The Oracle adaptor on NT requires the Oracle 8.0, 7.3, or 7.2 Client Library. It won't work with the 7.1 libraries. Informix Phone: (800) 331-1763 or call your local sales representative Ask for: ESQL/C version 7.2 for Win32 Notes Specific to PDO Developers To use Enterprise Objects Framework on PDO, you must have the appropriate database client libraries. Here's what you need: Oracle Phone: (800) 542-1170 or call your local sales representative Ask for: 7.3.2 SQLNet V2 TCP/IP Client libraries Informix Phone: (800) 331-1763 or call your local sales representative Ask for: ESQL/C Version 7.20.UC2 Sybase Phone: (800) 685-8225 or call your local sales representative Ask for: OpenClient/C Version 11.1 On PDO applications must explicitly link against the adaptor framework and the client libraries. New makefiles look for adaptor frameworks and automatically add in the right linker arguments. Simply add the adaptor framework to your project, and set the requisite environment variable specifying where the client libraries are installed. For Oracle set ORACLE_HOME and optionally ORACLE_REL. (The ORACLE_REL flag controls which set of libraries are used. It uses the Oracle 7.3 static link libraries by default, but you can also specify "8.0-static" or "7.3-dynamic.") For Sybase set SYBASE_HOME. For Informix set INFORMIX_HOME. If you use dynamic libraries on Solaris, you need to set the LD_LIBRARY_PATH environment variable when running your application. Database Client Libraries This section includes some tips on using database client libraries with Enterprise Objects Frameworks. It is organized by database vendor. Oracle On Windows NT, using the latest release of the client library (7.3) requires you to use SQL*Net v2, which requires a tnsnames.ora file. tnsnames.ora is a file that you put on client machines, generally in the directory Orant/Network/Admin. The file contains information needed to connect to a server over the network. Entries in tnsnames.ora are keyed off of a server ID alias, and they include information such as the server ID, the host machine name, and the network protocol used by the client library to resolve the server ID alias. An entry in tnsnames.ora might resemble the following: myServerAlias = (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp) (HOST=myMachine) (PORT=1521))(CONNECT_DATA=(SID=eof))) Oracle provides tools you can use to create tnsnames.ora files. Refer to your Oracle documentation for more information on tnsnames.ora files and the tools you can use to create them. If you're using the 7.2 version of the Oracle client libraries on Windows NT or if you're using Mach clients, you can use either SQL*Net v1 or SQL*Net v2. To use SQL*Net v1, you should set your adaptor's connectionDictionary serverId entry to "T::". To use SQL*Net V2 on Mach clients, you should create a tnsnames.ora file and put it in the /etc directory. Informix If you get the error "INFORMIXSERVER not in sqlhosts file (25596)" but can connect to your database server using the Informix ilogin program, you may need to run SetNet32 to update the environment variables used by Informix. The Informix client libraries appear to have redundant sources of server information. They use the sqlhosts file ($INFORMIXDIR/etc/sqlhosts) as well as a collection of environment variables managed by the Setnet32 program. See your Informix documentation for more information on the sqlhosts file and the Setnet32 program. New Features for 2.2 Java-wrapped Access and Control Layers EOF 2.2 includes: * Java-wrapped versions of the EOAccess and EOControl frameworks, so that you can write your Enterprise Object classes and Enterprise Objects Framework code in Java. * A Java class browser demo application for browsing Java APIs, available in NextDemos/JavaBrowser.app. EOModeler * EOModeler can generate template code for Java enterprise object classes. * Reverse engineering incorporates more schema information from your database into newly created models. Framework EOF 2.2 provides: * Caching of to-many array faults that greatly reduces faulting (especially in WebObjects applications), thereby improving performance. * A new insensitive like qualifier. Locating the Documentation for this Release The documentation for this release is provided in HTML and PDF formats. You can locate and view the documentation using the WebObjects Home Page. On NT, click the Start button and choose WOHomePage in the WebObjects program group. Or open the home page in a web browser directly, using the file /WebObjects/Documentation/WOHomePage.html. In addition to the documentation listed in the home page, this release also includes the document Differences Between Enterprise Objects Framework 1x and 2.0 on-line, which describes how the product has changed between the 1x and 2.0 releases. It is located in the directory: /NextLibrary/Documentation/NextDev/EnterpriseObjects/1x_To_2. Problems with Reading PDF Files If you're using the Acrobat Reader to view PDF files on Windows NT, some text may initially appear as gray lines. If this happens, you can fix it by choosing File -> Preferences -> General. In the General Preferences panel, uncheck the Greek Text option. Documentation Feedback Your comments on our documentation are especially valuable. Please send electronic mail with your comments and suggestions to techpubsfeedback@group.apple.com. Installing the Examples This release provides on-line examples to help familiarize you with Enterprise Objects Framework 2.x. These examples are located in /NextDeveloper/Examples/EnterpriseObjects. For more information on installing and building the examples, see the ExamplesGuide within the examples directory or refer to Post Installation Instructions, which is accessible from the WebObjects Home Page. Known Problems in Release 2.2 This section describes known problems with release 2.2 of Enterprise Objects Framework. It is organized into the following sections: * Java-wrapped Access and Control Layers * Access Layer * Control Layer * Miscellaneous Framework * Informix Adaptor * ODBC Adaptor * Oracle Adaptor * Sybase Adaptor * EOModeler * On-line Examples * Documentation Java-wrapped Access and Control Layers These problems exist in the Java-wrapped versions of the Access and Control layers of this Enterprise Objects Framework release: Reference: 81432 Problem: Key-value coding invocations raise if the provided key is different in Java from what it is in Objective-C. Description: If you use key-value coding to invoke a method whose name is different in Java from what it is in Objective-C (for example, ImmutableVector.size is mapped to [NSArray count]), the key is unbound on the Objective-C side and an exception is raised. Workaround: In key-value coding invocations, use the Objective-C keys instead of their Java counterparts. Reference: 81711 Problem: valueForKey raises an unbound key exception if the Objective-C method corresponding to the provided key returns void. Workaround: If you're writing Objective-C code that you're going to bridge, write Objective-C methods that return a value (instead of void). Access Layer These problems exist in the access layer of this Enterprise Objects Framework release: Reference: 81863 Problem: There isn't a publicly available method to turn off to-many array fault caching. Workaround: If you need to turn off to-many array fault caching for any reason (if you've implemented your own solution, for example), invoke the following method before the creation of any instances of EODatabase or EODatabaseContext. Calling it from main() would be good. [EODatabaseContext _setUseToManyCaching:NO]; Reference: 82008 Problem: NSNumber with value 0 is still taken to be NULL for primary key. Description: Starting in EOF 2.2, the EODatabaseContext assumes that an object with a single attribute primary key with a value of zero must be a newly created instance. And as such, the database context will attempt to get a new primary key for the object via delegate hook or the adaptor-specific primary key generation mechanism. This change allows users to use scalar data types (such as int) as an enterprise object's primary key, and still rely on EOF automatic primary key generation. Unfortunately, if you have an existing database containing rows that have a primary key of 0, an attempt to update an object created from such a row will cause the database context to incorrectly assume that an object created from such a row needs to get a new primary key. This can leave invalid foreign key references in other tables. Workaround: Implement the EODatabaseContext delegate method databaseContext:newPrimaryKeyForObject:entity: to catch the case where the framework is going to mistakenly get a new key. From EODatabaseContext.h: - (NSDictionary *)databaseContext:(EODatabaseContext *)context newPrimaryKeyForObject:(id)object entity:(EOEntity *)entity; // If a newly inserted EO doesn't already have have a primary key set, // this delegate is called to generate a key. If the delegate is not implemented, // or returns nil, then the DatabaseContext will call // [EOAdaptorChannel primaryKeyForNewRowWithEntity:(EOEntity *)entity] // to attempt to generate the key. Example of how to get the database context and set its delegate: { ... model = [[EOModelGroup defaultGroup] modelNamed:@"myModel"]; dbContext = [EODatabaseContext registeredDatabaseContextForModel:model editingContext:editingContext]; [dbContext setDelegate:self]; ... } Example of a delegate method implementation: - (NSDictionary *)databaseContext:(EODatabaseContext *)context newPrimaryKeyForObject:(id)object entity:(EOEntity *)entity { if (entity == entityThatIKnowHasAValidRowWithAKeyOfZero) if ([[object valueForKey:primaryKeyThatCanBeZero] isEqual:[NSNumber zero]]) return [NSNumber zero]; return nil; } Reference: 77721 Problem: Can't update rows containing string attributes with trailing spaces. Description: The Enterprise Objects Framework adaptors automatically strip trailing spaces from string values fetched from the database. They also strip spaces on newly inserted strings before sending them to the database. This works fine until you fetch data that a non-Enterprise Objects Framework application inserted that contains trailing spaces. If that attribute is marked as "used for locking," Enterprise Objects Framework will be unable to update the row (because the version in the database is different from the space-stripped version in the snapshot). Workaround: Do not mark columns that could contain trailing spaces as used for locking. Alternately, strip the spaces from the data in your server. Reference: 77546 Problem: Inclusion of framework models in defaultModelGroup doesn't happen automatically on PDO. Description: Applications on PDO that link with frameworks that include models don't automatically get the models put in the applications. Workaround: Manually construct the the model group yourself at application initialization. For example: EOModelGroup *group = [EOModelGroup new]; // repeat for each model containing framework used by app NSBundle *bundle = [NSBundle bundleForClass:[SomeClassInFramework class]] NSEnumerator *enumerator = [[bundle pathsForResourcesOfType:@"eomodeld" inDirectory:nil] objectEnumerator]; NSString *modelPath; while (modelPath = [enumerator nextObject]) [group addModelWithFile:modelPath]; [EOModelGroup setDefaultGroup:group]; [group release]; Reference: 77631 Problem: If you're editing a model (in code or with EOModeler), sometimes an EORelationship will return nil from inverseRelationship, even though you just added the inverse relationship. Description: The first time you ask an EORelationship for its inverse relationship, it searches all the relationships in its destinationEntity looking for an inverse. It caches the result of this search, and this cache does not always get invalidated when the relationships of the destinationEntity change. Workaround: See the category on EORelationship in the ModelerBundle/RelationshipExtras.m example. Reference: 77354 Problem: Problems saving changes to attributes with mutable custom value objects. Description: Suppose you have a mutable custom value type, PhoneNumber, that implements methods such as setAreaCode: and setPrefix: to change an enterprise object's values. If you use such methods to modify an enterprise object's values and save changes, the enterprise object is not saved to the database. Workaround: To use mutable value classes you must do three things: 1. In the PhoneNumber value class object, implement isEqual: to appropriately compare two instances. 2. If the PhoneNumber value is about to be modified, its owning enterprise object must invoke [self willChange] before the modification. 3. In your enterprise object class, you must implement a "set" method that copies rather than retains the object passed to it. For example: - (void)setDayTimePhone:(PhoneNumber *)number { [dayTimePhone autorelease] dayTimePhone = [number copy]; } #1 would be required, even in a perfect world. #2 is a requirement of the basic Enterprise Objects Framework architecture. #3 is a bug in Enterprise Objects Framework -- Enterprise Objects Framework should be passing enterprise objects a copy of their values, but instead it's passing the the same instance that's shared in the snapshot. In general, the simplest workaround is to use immutable custom value objects. Reference: 72619 Problem: EOAdaptorChannel does not inherit EOAdaptor's delegate. Description: According to the EOAdaptorChannel class specification and header file, the EOAdaptorChannel's delegate should automatically be kept in synch with its adaptor. Indeed, if a new delegate is assigned to an EOAdaptor, the new delegate is propagated to any of that adaptor's existing contexts and channels. However, if you create an EOAdaptor, assign a delegate to it, and then create EOAdaptorContexts and EOAdaptorChannels, the newly-created contexts and channels don't have the delegate assigned to them. Workaround: Wait until all of the channels and contexts are instantiated before assigning the adaptor's delegate, or reassign the adaptor's delegate each time a new channel or context is created. Reference: 61475 Problem: Enterprise Objects Framework performs less efficient deep fetches for single-table inheritance mappings than it should. Description: To perform a deep fetch, Enterprise Objects Framework performs a fetch for each concrete class in an inheritance hierarchy. For a single-table inheritance mapping, Enterprise Objects Framework should perform only one fetch and then sort the results in memory. For example, if Person, Employee, and Customer objects are stored in one table--the PERSON table--the Framework should perform one fetch on the PERSON table to fulfill a deep fetch request of Person, Employee, and Customer objects. Instead, it performs three fetches: one to get Person objects, one to get Employee objects, and another to get Customer objects. Workaround: Define only one entity for the entire inheritance hierarchy, and use the EOModelGroup delegate methods subEntityForEntity:primaryKey:isFinal:, and entity:classForObjectWithGlobalID: to create instances of the proper subclasses from database rows. Reference: 74251 Problem: Changes made during saveChanges are silently lost. Description: If you change an enterprise object while its editing context is in its saveChanges method (for example, if you change an enterprise object in an EODatabaseContext delegate method), the changes may be silently lost. Workaround: Don't make changes to objects during the save process. Instead, make the changes from the EOEditingContext delegate method editingContextWillSaveChanges:. Reference: 74345 Problem: You can't update to-many relationship if the foreign key isn't marked as a class property or as used for locking. Description: Suppose that an entity's foreign key attribute isn't marked as a class property or as used for locking. If you designate the foreign key attribute as a to-many relationship's destination key, the foreign key value isn't always updated. This occurs because the destination entity doesn't know that the attribute participates in a relationship. Therefore, the destination entity doesn't fetch the foreign key from the database or update it. Workaround: Mark attributes that are destination keys of a to-many relationship so they are fetched. For example, you could: * Mark them as class properties. * Mark them as used for locking. * Use them in inverse relationships to the problematic to-many's source entity. Reference: 74379 Problem: EODatabaseContext can't be the direct parentObjectStore of an EOEditingContext. Description: The EODatabaseContext requires that an EOObjectStoreCoordinator sit between it and any EOEditingContexts that it serves. This is the default configuration set up by the framework, so you shouldn't normally run into this problem. Just a reminder, you can set up an editingContext and be ready to go with this one line: EOEditingContext *editingContext = [EOEditingContext new]; // automatically uses [EOObjectStoreCoordinator defaultCoordinator] // as parentObjectStore Any necessary EODatabaseContexts are created and registered automatically. Workaround: Don't assign an EODatabaseContext as the parentObjectStore of an EOEditingContext. There's no benefit to doing so anyway. Reference: 76526 Problem: Applying a qualifier with key path to top of horizontally mapped inheritance hierarchy generates invalid SQL. Description: Enterprise Objects Framework's query building mechanism doesn't handle relationships to inheritance hierarchies. For example, suppose that you are are attempting to qualify a fetch through a to-many relationship (planes) that points to the top of a horizontally mapped inheritance hierarchy (for the entities Plane, FighterPlane, and TrainerPlane). If you want the query to test against all tables, you'd expect Enterprise Objects Framework to generate SQL similar to the following: SELECT t0.AIRPORT_ID FROM PLANE t1, FIGHTER t2, TRAINER t3, AIRPORT t0 WHERE (t1.LENGTH <= 1000 AND t0.AIRPORT_ID = t1.AIRPORT_FK) OR (t2.LENGTH <= 1000 AND t0.AIRPORT_ID = t1.AIRPORT_FK) OR (t3.LENGTH <= 1000 AND t0.AIRPORT_ID = t1.AIRPORT_FK) Instead, Enterprise Objects Framework generates the following SQL: SELECT t0.AIRPORT_ID FROM PLANE t1, AIRPORT t0 WHERE (t1.LENGTH <= 1000) AND t0.AIRPORT_ID = t1.AIRPORT_FK In other words, only the table for the root of the hierarchy is queried. Workaround: You can create a qualifier that generates the correct SQL by: 1. Adding relationships in the source entity to all the tables in the inheritance hierarchy. For example, to the Airport entity, you'd add the relationships toFighters and toTrainers to the destination entities FighterPlane and TrainerPlane, respectively. Mark the relationships so they aren't class properties. 2. When building your query, explicitly list these extra relationships. In the Planes example, you'd fetch from Airport where "planes.length < 1000 OR toFigtherPlanes.length < 1000 OR toTrainerPlanes.length < 1000" Alternatively, you might be able to solve this problem more generally by writing a post processor for EOQualifiers that splits up clauses that perform inheritance tests. The post processor could even programmatically generate the additional relationships on demand and register them with the model using names like "plane_Subclass_Fighter". A generic EOQualifier post processor could be wired into Enterprise Objects Framework so that application writers don't have to know it exists. The right place for such a mechanism is probably in EOKeyValueQualifier's schemaBasedQualifierWithRootEntity: method (see EOSQLQualifier.h). You could put the post processor code in a subclass of EOKeyValueQualifier (with an appropriate call to super after the transformation, if any, is performed) and have your subclass pose as EOKeyValueQualifier. Reference: 47832 Problem: Enterprise Objects Framework can't update attributes whose internal types are custom (such as NSImages). Description: A custom value class must implement isEqual: to be used for attributes marked as used for locking. Workaround: Implement isEqual: in the custom value class or don't mark the attribute as used for locking. Reference: 65078 Problem: Seemingly innocuous qualified fetch always causes exception. Description: Some qualified fetches raise exceptions because values in the SQL have been formatted as strings when they should have been formatted as some other type. This can happen when you enter an invalid external type or when a Sybase model doesn't contain information about user-defined types that are used in the model. Workaround: In the case of an invalid external type, simply correct it. In the case of a user defined type, create a new model by reverse engineering the database. The new model's connection dictionary contains information about user-defined types. Copy the connection dictionary from the new model to the original one. Reference: 69039 Problem: Alert panel displaying adaptor error is never dismissed. Description: This occurs whenever an adaptor operation that was invoked from an awakeFromNib: method displays an alert panel. The problem is that the entire object graph is not yet instantiated when awakeFromNib: is invoked. Workaround: Database operations should be begun from the applicationDidFinishLaunching: method rather than the awakeFromNib: method. Of course, this means that any methods that indirectly cause database communication should also be invoked from the applicationDidFinishLaunching: method. Reference: 76885 Problem: The set of valid values for the databaseEncoding entry of a connection dictionary are not documented, and the set can vary in different locales. Description: A connection dictionary's databaseEncoding entry contains the localized name for the string encoding. The localized names are not documented. Furthermore, the localized names for string encodings can vary with the user's locale. Consequently, the specified encoding for an application might not work for users in different locales. Workaround: You can find the localized name for string encodings in /NextLibrary/Frameworks/Foundation.framework/Resources/language.lproj/EncodingNames.strings. Reference: 59472 Problem: Derived attributes are limited and don't offer full SQL as advertised. Description: Placing a string or a numeric constant in the definition field of a derived attribute generates invalid SQL. Definitions such as ``title'' and ``0.0'' don't work correctly. However, definitions such as ``att1 + 5'' should work correctly when ``att1'' specifies another attribute. Workaround: None. Reference: 70049 Problem: EOModelGroup doesn't raise an exception when more than one entity has the same name. Description: Although it is illegal to have the same entity name in two different models in a model group, EOModelGroup doesn't check to see if this is the case when adding a model. Workaround: Manually verify that no two models have entities with the same name or write a method to perform the check. Reference: 70260 Problem: Some error messages returned by the Framework's default validation methods (such as methods that check that a value doesn't exceed the maximum width specified in its attribute) aren't localized. Workaround: Implement an exception handler for use with the EOEditingContext, and have the handler replace the error messages with localized strings. Reference: 76152 Problem: Inserting and deleting objects involved in inverse, to-many relationships can be very slow. Description: Suppose that a ServiceRequest has a to-one relationship to its CustomerServiceRepresentative, and that the CustomerServiceRepresentative has an inverse to-many relationship to its ServiceRequests. When you assign a request to a representative using addObject:toBothSidesOfRelationshipWithKey:, you fire the fault for the CustomerServiceRepresentative.serviceRequests. So, if a representative has a large number of requests, assigning a new request to a representative can be very slow. Correspondingly, when you delete a request, Enterprise Objects Framework fires the corresponding representative's serviceRequests fault so it can remove the request from the array. Workaround: Set the inverse, to-many relationship so it isn't a class property. For example, in the above request-representative scenario, you would remove the serviceRequests relationship from the class properties of the CustomerServerRepresentative entity. Reference: 82173 Problem: EOAdaptorChannel.h has an erroneous comment for the method fetchRowWithZone:. Description: When fetchRowWithZone: returns nil signalling the end of the result set, isFetchInProgress can return YES to indicate that there are more result sets. The comment should read: - (NSMutableDictionary *)fetchRowWithZone:(NSZone *)zone; // Fetches the next row from the result set of the last // -selectAttributes:... message and returns values for the attribute // names in attributes. When no rows are left, this method invokes // adaptorChannel:didFinishFetching:, and returns nil. // For adaptors that can have multiple result sets (ODBC and Sybase), // This method will return nil at the end of each result set, however // isFetchInProgress will return YES. The channel will also send the // delegate an an adaptorChannelDidChangeResultSet: message whenever // the end of one result set has been reached and another one is // pending. // This methods may raise an exception if an error occurs. Control Layer These problems exist in the control layer of this Enterprise Objects Framework release: Reference: 82210 Problem: Attempt to copy an EOSortOrdering object throws an exception: *** -[EOSortOrdering copyWithZone:]: selector not recognized Workaround: Don't copy EOSortOrderings, or implement copyWithZone: in a category on EOSortOrdering. Reference: 68146 Problem: Fault failure leaves EOInterface layer unstable. Description: If a displayed enterprise object has a to-one relationship to a non-existent destination row, attempting to access the destination object raises an exception and corrupts the state of user interface objects. (Enterprise Objects Framework raises an exception when a to-one relationship cannot be resolved due to a referential integrity problem in the database). Workaround: See the chapter "Advanced Enterprise Object Modeling" in the Enterprise Objects Framework Developer's Guide for information on handling optional to-one relationships. Reference: 64084 Problem: Inserted enterprise objects don't get removed from EODisplayGroup after sending revert to EOEditingContext. Description: If you fetch objects into an EODisplayGroup, insert a few objects, delete a few objects, and then update a few objects; telling the EOEditingContext to revert backs out the updates, but not insertions or deletions. The actual insertions and deletions have been reverted, but the EODisplayGroup doesn't know how to revert its object list (since is doesn't keep track of what its original object list was before the insertions and deletions). Workaround: Programmatically tell all affected EODisplayGroups to refetch after telling the EOEditingContext to revert, or use refetch: (invalidateAllObjects:) instead of revert. Reference: 72177 Problem: Deleted objects are still registered in the EOEditingContext after a saveChanges operation. Description: If an object is deleted in the EOEditingContext and then the EOEditingContext is saved, the deleted object isn't forgotten by the EOEditingContext (i.e., sending the EOEditingContext the message objectForGlobalID: should return nil, but it doesn't). Workaround: Fortunately, this should have no affect on most applications. However, if you need to work around this problem, remember the deleted objects in the editingContextWillSaveChanges: delegate, and then invoke forgetObject: for each object after a successful save. Reference: 72269 Problem: You can't tell Enterprise Objects Framework to not undo your changes when delete propagation fails. Description: The EOEditingContext delegate method editingContextShouldUndoUserActionsAfterFailure: is supposed to allow programs to indicate that they do not want user actions undone if a validation or delete propagation error occurs. However, the EOEditingContext undoes the user action regardless of the return value from the method. Workaround: None. Reference: 72903 Problem: Aborted deletions are incorrectly recorded in the undo stack as empty undos. Description: When the deletion of an object fails due to a deny rule, the undo manager records an empty undo group. This means that although nothing actually happened during the operation, the operation still needs to be undone before previous operations can be undone. For interactive programs this is not normally a problem since users rely on visual cues to determine how many times to undo. However, this may be a problem for code that programmatically performs undo operations. Workaround: None. Reference: 74965 Problem: The EOEditingContext delegate method editingContext:shouldPresentException: isn't called when saveChanges is invoked programmatically. Description: If you use the following code: eo = [[[Movie alloc] init] autorelease]; [eo setTitle:nil]; // Assume that the TITLE column doesn't allow NULLs [editingContext insertObject:eo]; [editingContext saveChanges]; the editingContext:shouldPresentException: delegate method isn't called. Instead, an exception is raised. However, if you instead set a user interface control object as the target for the editing context's saveChanges: action, the delegate method is invoked. Workaround: Always use saveChanges: instead of saveChanges. If you don't have an argument to pass, just use [editingContext saveChanges:nil]; Reference: 76466 Problem: EOEditingContexts don't propagate uninserts. Description: Propagate delete works fine for an object that that is fetched from the database. However, if an object is created and inserted in an editing context and then deleted (thus never being saved to the database), the delete isn't propagated to the destinations of the object's relationships. For example, suppose you create an ExpenseReport object and several LineItems for it. If you then delete the ExpenseReport, the delete doesn't propagate to the LineItems. If the LineItems can't exist without an owning ExpenseReport, EOEditingContext's saveChanges fails when the delete is performed within the same event as the insert. Workaround: Call [editingContext processRecentChanges] before deleting the previously inserted object. Reference: 76901 Problem: Associations are refreshed too early when a modal panel (such as the fetch limit panel) is raised, possibly causing an exception. Description: Suppose you have two EODisplayGroups that are set to fetch on load. If the second display group to fetch exceeds the fetch limit, an alert panel inquiring whether to continue the fetch pops up. Presenting the panel causes the run loop to flush the first display group's user interface drawing. If the first display group's user interface displays enterprise object properties via key paths, EOFaults may be fired. Since the default EODatabaseChannel is busy with the fetch for the second display group, an exception is raised because there isn't an available channel. Workaround: There are several workarounds: 1. Don't use the fetch "prompt on limit" feature. 2. If your application only uses modal panels for alerts and warnings, disable the modal refresh by sending the following message in your application's initialization code (make sure to awake the EODisplayGroup first so it's initialize method is called before you send this message): [[EODelayedObserverQueue defaultObserverQueue] setRunLoopModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]] 3. Implement your own fetch limit panel that doesn't invoke a modal event loop. 4. Register an additional EODatabaseChannel with the EODatabaseContext so the fetch of the faults can occur while the second EODisplayGroup fetch is paused. Reference: 77181 Problem: The EOQualifier contains operator doesn't do SQL generation. Description: The contains operator is meant to do to-many array comparison. For example, you might query on the Studio entity using the following qualifier format: "movies contains %@", someMovieObj The resulting qualifier works for an in-memory search, but doesn't generate SQL for a database search. On the other hand, using the equality operator for to-many array comparison kind of works in SQL, but not in memory. For example, you might query on the Studio entity using the following qualifier format: "movies = %@", someMovieObj The resulting qualifier returns no matches when evaluated in memory because the array property is not equal to the movie object as determined by isEqual:. However, when it's evaluated in the database, it returns the same studio N times (where N is the number of movies in the Studio's movies array), even though the qualifier is attempting to match only one movie. Workaround: Use the contains operator for qualifiers in-memory evaluation and the equality (=) operator (with usesDistinct on the fetch specification) for evaluation in the database. Miscellaneous Framework These problems exist in this Enterprise Objects Framework release: Reference: 46679 Problem: Enterprise Objects Framework's private instance variables aren't declared @private and don't have names that begin with the underbar ('_') character. Description: All instance variables in Enterprise Objects Framework should be considered private. Workaround: Don't directly access Enterprise Objects Framework instance variables. Reference: 69211 Problem: Link errors on Windows NT. Description: Programs on Windows NT must add explicit references to at least one class in each framework in order to avoid link errors at run time. Workaround: Add a function like that in the following code snippet, which refers to classes in each of Enterprise Objects Framework's layers. Though never invoked, it forces the appropriate linking to occur. #ifdef WIN32 #import #import #import void _referenceAllEOFrameworks() { [EODisplayGroup new]; // EOInterface [EOEntity new]; // EOAccess [EOEditingContext new]; // EOControl } #endif If you create your project with the type "EOApplication," this code is automatically added to your project main file. Reference: 72027 Problem: EOKeyValueCoding is broken for doubles on HPUX PDO. Description: EOKeyValueCoding doesn't work correctly for accessor methods that set and return doubles on HPUX under PDO 4.1 (and previous releases). This means that users cannot correctly fetch enterprise objects that have class properties with accessor methods that use doubles. Workaround: Change your enterprise objects' accessor methods to return and take as arguments NSNumbers, NSDecimalNumbers, or ints. Informix Adaptor These problems exist in the Informix adaptor supplied with this release of Enterprise Objects Framework: Reference: 64031 Problem: Informix adaptor user defaults for Enterprise Objects Framework 2.x are different than those for Enterprise Objects Framework 1.2. Description: In Enterprise Objects Framework 1.2, the InformixAdaptor stores defaults in the EOFInformixAdaptor domain and uses the following keys: INFORMIXDIR, DBDATE, DBLANG, DBMONEY, InformixLogErrors, ShowSystables, ShowTableOwner, Beautify, DefaultIsolationLevel, GlobalOptimization, GlobalExplain, GlobalLockMode, GlobalPDQPriority, GlobalDataSkip, GlobalConstraints, DatabaseExclusive Enterprise Objects Framework 2.x stores defaults in the standard NSGlobalDomain and prefixes all keys with ``Informix'', that is: InformixINFORMIXDIR, InformixDBDATE, InformixDBLANG, InformixDBMONEY, InformixLogErrors, InformixShowSystables, InformixShowTableOwner, InformixBeautify, InformixDefaultIsolationLevel, InformixGlobalOptimization, InformixGlobalExplain, InformixGlobalLockMode, InformixGlobalPDQPriority, InformixGlobalDataSkip, InformixGlobalConstraints, InformixDatabaseExclusive. Workaround: None. Reference: 70232 Problem: Informix adaptor raises an exception when you try to sort on attributes that are not in the select list. Description: Due to a restriction in the Informix adaptor, it's not possible to sort on attributes that aren't included in the select list. This means that it isn't possible to sort the results using an attribute that is not marked on the entity as either a primary key, used for locking, or a class property. Workaround: If possible, add the attribute to the entity and mark it as used for locking. Otherwise, there is no workaround. ODBC Adaptor These problems exist in the ODBC adaptor supplied with this release of Enterprise Objects Framework: Reference: 81774 Problem: Can't save large BLOB's to SQLServer Description: If you try to save large BLOB's (more than 1 meg), you will probably encounter a segmentation violation. This is happening because something in the ODBC stack can't handle large buffers. Workaround: You can add a special EOF flag to the driverInfo dictionary that will cause EOF to use the SQLPutData() function to break up large BLOB's into smaller pieces for transmission. To enable this behavior, add the following line to your driverInfo dictionary in the EOModel. EOF_ENABLE_SQLPUTDATA = Y; Starting with EOF 2.2, this flag is always set when you reverse engineer a model, but older models created with EOF 2.1 or EOF 2.0 will not have the flag. Warning to users of MS-Access: The ODBC Access driver doesn't handle the SQLPutData() calls correctly, so Access users should not turn this flag on. It will be set to "N" by default when reverse engineering an Access database. Oracle Adaptor These problems exist in the Oracle adaptor supplied with this release of Enterprise Objects Framework: Reference: 82299 Problem: On NT, you can't use gdb on an app running against the oracle adaptor. Description: It has been reported that running gdb on an application running against the OracleAdaptor can sometimes result in unexplained crashes or hangs, even when the same application works when run from outside the debugger. It seems that something in the Oracle Tracing mechanism causes the entire process to behave unpredictably when running within gdb. Some people never see this problem, others may see it occasionally, some may never be able to run gdb acceptably. Workaround: There are several ways to deactivate this tracing. The easiest is to remove tracing from the registry by renaming the HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\OTRACE73 entry. Reference: 77517 Problem: If you try to update an enterprise object with an attribute that maps to a LONG RAW column while using on-demand locking, you get the following exception: "fetchObject -- EODatabaseChannel 0x12345678: attempt to lock object that has out of date snapshot" Description: It appears that the Oracle database sometimes returns wrong BLOB values when it's passed "SELECT ... This statement fails with the ORA-01786 error. The Oracle RDBMS doesn't support the use of DISTINCT with the FOR UPDATE clause. Workaround: If you use the pessimistic locking mode against an Oracle database, you can't use the batch faulting or prefetching features. Reference: 62425 Problem: Oracle Adaptor doesn't read stored procedures inside of packages. Description: There is no way to get the database to tell you the components (procedures and functions) that are inside a package definition. Clients can still create stored procedures in the model that will call into packages, it's just that model description using EOModeler won't create these at connect time. Workaround: You can use EOModeler to create the stored procedure definitions in the model. Just set the external name of the stored procedure to package-name.procedure-name. Reference: 73333 Problem: The Oracle adaptor has character set problems on Sparc and m68k. Description: The Oracle adaptor on Mach does not properly support certain character set conversion on certain architectures: * On SPARC ISOLatin1 works, but Japanese character sets do not. * On m68k non-ASCII ISOLatin1 characters are stripped and Japanese character sets don't work at all. On Intel all character sets work fine, including European and Japanese. Workaround: To get non-ASCII character sets on SPARC and m68k, install the EO2JOracleAdaptor.pkg that's on the Enterprise Objects Framework 2.1 Mach CD. Note: The EO2J Oracle Adaptor is built with the 7.0 version of the Oracle client libraries. Consequently, returning fetch sets from stored procedures is not supported. Reference: 77990 Problem: Sometimes when you run the install_database script or use the schema object creation window in EOModeler, you might get one of the following errors. Mar 27 10:19:34 eoutil[1577] Exception running dump: ORA-00955: name is already used by an existing object create table !!! eo_temp_table as select max(MOVIE_ID) counter from MOVIE Mar 27 10:27:54 eoutil[1591] Exception running dump: ORA-00955: name is already used by an existing object create procedure !!! eo_set_sequence is xxx number; yyy number; begin select max(counter) into xxx from eo_temp_table; if xxx is not NULL then yyy := 0; while (yyy < xxx) loop select MOVIE_SEQ.nextval into yyy from dual; end loop; end if; end; Description: If the primary key support code dies unexpectedly, it can leave the eo_set_sequence stored procedure and the eo_temp_table table in the user's schema. This isn't a problem right away, but any subsequent attempt to run the install_database script will fail because the statements that attempt to create these schema objects will fail and the data loading will stop before it is finished. Workaround: Use the following commands from SQLPlus to remove these objects before you attempt to create the schema objects with the install_database script. SQL> drop table eo_temp_table; SQL> drop procedure eo_set_sequence; Sybase Adaptor These problems exist in the Sybase adaptor supplied with this release of Enterprise Objects Framework: Reference: 62634 Problem: The Sybase adaptor uses CS_CONVERT() to convert numeric data into NSDecimalNumbers. Description: Fetching decimal numbers in locales that use a characters other than `.' for the decimal may not work. Workaround: None. Reference: 63169 Problem: Models created for version 4.9 Sybase servers do not include stored procedures. Description: EOModeler gets stored procedure information using functionality that isn't provided in old servers. Workaround: Use EOModeler's Stored Procedure Editor to add EOStoredProcedure objects to a model. Reference: 74633 Problem: You can't link against the Sybase1x framework. Description: The Sybase1x framework has a bug in its sybase1x.lib, such that anything linked against it attempts to load the nonexistent Sybase.dll (rather than Sybase1x.dll). If you never access an adaptor-specific class such as SybaseChannel, you won't have problem. However, if you do reference an adaptor-specific class, your application (or framework) won't be able to initialize. Workaround: Make a copy of the Sybase1x.dll named Sybase.dll. Reference: 75024 Problem: The SQL generation for primary key support in the Sybase adaptor isn't sufficient. Description: The SQL generated by EOModeler to support primary key generation in Sybase simply invokes the sp_primarykey stored procedure. sp_primarykey adds useful information to the syskeys table, but doesn't create constraints that enforce uniqueness (or NOT NULL) in the primary key columns. Workaround: Add the constraints yourself using statements of the following form: alter table add constraint primary key ( {, 0 order by a.name EOSybaseRelationshipSQL Default is select a.keycnt, b.name tname, c.name cname, d.name dtname, e.name dcname from syskeys a, sysobjects b, syscolumns c, sysobjects d, syscolumns e where (b.type = 'U' or b.type = 'V') and a.depid is not null and a.depid > 0 and b.id = a.id and b.id = c.id and ((c.colid = a.key1 and e.colid = a.depkey1) or (c.colid = a.key2 and e.colid = a.depkey2) or (c.colid = a.key3 and e.colid = a.depkey3) or (c.colid = a.key4 and e.colid = a.depkey4)) and d.id = a.depid and d.id = e.id order by b.name, d.name EOSybaseStoreProcedureSQL Default is select name, id from sysobjects where type = 'P' EOSybaseStoredProcedureDetailsSQL Default is sp_sproc_columns %@ InformixINFORMIXSERVER No default value. The name of the Informix server. InformixInformixTableNamesSQL This default can be used to change the default SQL used to determine the tables that will be analyzed in creating a new model. Default is select tabname, owner, tabid from informix.systables where (tabid > 99) and (tabname <> 'ANSI') order by tabname Defaults in the EOModeler Domain To change these defaults, issue a command such as the following from a shell: defaults write EOModeler DisableInheritenceCheck YES BundlesToLoad If you write extensions to EOModeler, you can get EOModeler to load them by setting this default. This default is an array, so remember to include parentheses when you set it. For example: defaults write EOModeler BundlesToLoad "(/LocalDeveloper/ModelerBundles/MyModelerBundle.bundle, $HOME/eoexamples/ModelerBundle/ModelerBundle.bundle) " RECORD_FETCH_LIMIT Default is 100. For the Data Browser in EOModeler. This controls how many rows to fetch before asking users if they want to fetch all, fetch another n rows, or just stop now. Consistency Checks All of the following defaults have the default NO: DisableConsistencyCheckOnSave DisableExternalNameCheck DisableInheritenceCheck DisablePrimaryKeyCheck DisableRelationshipCheck DisableStoredProcedureCheck SkipBeautifyNamesOnModelCreation Default is NO. Setting this default to YES will cause EOModeler to leave the entity names and attribute names matching the exact names of their corresponding database objects (including the case). DisableAdvancedOptions Default is NO. If set to YES, the EOModeler runs in "Simplified mode". The advanced inspectors don't appear, the choices of table view columns is limited, and so on.   1997 Apple Computer, Inc. All rights reserved. These Release Notes are for informational purposes only. Every effort has been made to ensure the accuracy of information contained in these Notes. However, Apple assumes no responsibility for the accuracy of the information and it is subject to change without notice. Any use of, or actions taken based upon, any information contained in these Notes is done at your own risk.