Changes for page Leveraging the Power of EOF
Last modified by Pascal Robert on 2011/05/21 10:26
From version 2.1
edited by Pascal Robert
on 2011/05/08 02:46
on 2011/05/08 02:46
Change comment:
There is no comment for this version
To version 3.1
edited by Pascal Robert
on 2011/05/21 10:04
on 2011/05/21 10:04
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -4,6 +4,89 @@ 4 4 5 5 == Fetching Objects == 6 6 7 +=== Objects Involved in Fetching === 8 + 9 +There are many objects involved in retrieving data in an Enterprise Objects application. The ones you'll most commonly work with are introduced here. 10 + 11 +EOFetchSpecification A fetch specification provides a description of what data to retrieve from a data source. A fetch specification always includes the name of an entity—in Enterprise Objects, a single database fetch operation is always done from the perspective of a particular entity. A fetch specification usually includes a qualifier—specific criteria to look for when searching the database. A fetch specification can also include a sort ordering, which specifies that the result set should be sorted in a particular way. 12 + 13 +EOQualifier A qualifier is often included in a fetch specification to provide criteria for a particular database fetch. There are a number of different kinds of qualifiers, some of which map to a SQL expression such as AND or OR. A qualifier is commonly compound—that is, a qualifier often consists of multiple qualifiers. 14 + 15 +EOSortOrdering A sort ordering is often included in a fetch specification to specify that the fetch's result set should be sorted in a particular way. 16 + 17 +EOEditingContext In Enterprise Objects, a fetch almost always takes place within an object workspace called an editing context. 18 +Other objects are involved in a fetch specification, such as EODatabaseContext and EOAdaptorChannel, but you rarely need to interact with these objects programmatically. 19 + 20 +=== Flow of Data During a Fetch === 21 + 22 +A fetch begins with the construction of a fetch specification. You can create fetch specifications programmatically, but they are also created by various components within a WebObjects application such as display groups. You can also use EOModeler to build fetch specifications. 23 + 24 +Once a fetch specification is created, the fetch must be initiated. Again, you commonly do this programmatically by invoking objectsWithFetchSpecification on an EOEditingContext, but it is also often done automatically by objects such as display groups. 25 + 26 +Once a fetch is initiated, the following sequence occurs to retrieve data from a data source: 27 + 28 +* When objectsWithFetchSpecification is invoked on an EOEditingContext, that editing context forwards the invocation on to its parent object store. The parent object store again forwards the invocation on to its parent object store until the root object store is reached (the root object store is usually an instance of EOObjectStoreCoordinator). 29 + 30 +* The root object store (EOObjectStoreCoordinator) determines which of its EOCooperatingObjectStores should service the fetch specification. It forwards the objectsWithFetchSpecification invocation to the determined cooperating object store to ask it to retrieve data from the data source. 31 + 32 +How does an EOObjectStoreCoordinator determine which of its EOCooperatingObjectStores should service a particular fetch specification? Remember that within an EOModelGroup, entity names must be unique. Also remember that fetch specifications are entity-centric—every fetch specification is specified on the basis of a particular entity. So an object store coordinator simply looks for the list of entities registered within its cooperating object stores to match an entity name to particular cooperating object store. 33 + 34 +When an EOCooperatingObjectStore receives a request to fetch data from a data source, it invokes objectsWithFetchSpecification on its EODatabaseContext object to do the work. When a database context receives this fetch request, it fetches a number of rows from the database, transforms them into enterprise objects (in most cases), and registers them as needed with the EOEditingContext that initiated the chain of objectsWithFetchSpecification invocations. 35 + 36 +A database context uses an EODatabaseChannel to do all this. That object in turn uses an EOAdaptorChannel object to communicate directly with data sources and model-level objects—EOEntity, EOAttribute, EORelationship—that are necessary to perform the fetch. 37 +Within EODatabaseContext, fetching occurs in two major steps: 38 + 39 +* A database context uses a database channel to select the rows in the database for which objects are being fetched. It does this using the EODatabaseChannel method selectObjectsWithFetchSpecification, which takes as an argument the fetch specification that originated in the editing context. 40 + 41 +* The database channel fetches each enterprise object, one at a time, as the database context repeatedly invokes on it the method fetchObject. This method uses state built up in the first step to get data from the object, create an enterprise object instance if necessary, and register the new instance with the fetch's editing context. The database channel uses the entity name specified in the fetch specification to know which enterprise object class to instantiate for every fetched object. 42 + 43 +When an EODatabaseChannel receives an invocation of fetchObject from an EODatabaseContext, the following sequence of events occurs: 44 + 45 +* The database channel uses an EOAdaptorChannel to retrieve a record for the requested entity. The record retrieved includes the record's primary key, class properties and client-side class properties, attributes used for locking, and any foreign keys used by the entity's relationships. 46 + 47 +* The database channel then assigns an EOGlobalID to the row by invoking globalIDForRow. 48 + 49 +* The database channel records a snapshot for the fetched row. A global ID may already have a recorded snapshot, but if this is not the case, the method recordSnapshotForGlobalID is invoked on EODatabase. However, if a snapshot is already recorded for the given global ID, the database context delegate method databaseContextShouldUpdateCurrentSnapshot is instead invoked. The default behavior does not update the already recorded snapshot with the new one, but you can change this by implementing the delegate method. 50 + 51 +At this point in the fetch, if the fetch specification is set to refresh refetched objects, an ObjectsChangedInStoreNotification is posted to invalidate (refault) any existing enterprise object instances that correspond to this global ID. 52 + 53 +* The database channel records whether the object was locked when it was selected. This would be the case only if you enable pessimistic locking (row-level locking) in your application. 54 + 55 +* The database channel then checks with the editing context in which the fetch originated to see whether a copy of the object already exists in that editing context. It uses the EOEditingContext method 56 + 57 +* If the editing context contains an enterprise object for the global ID and if that enterprise object is not a fault, the editing context returns the enterprise object. Otherwise, the enterprise object returns null. 58 + 59 +* If the editing context doesn't return an enterprise object for the global ID, the database channel invokes the EOEntityClassDescription method createInstanceWithEditingContext, which determines the object's class based on the fetch specification's entity and instantiates an object of that class. 60 + 61 +* The database channel invokes the method recordObject on the editing context to unique the newly created object. 62 + 63 +* If the editing context has a fault for the global ID, the fault is cleared and initialization proceeds just as if an empty enterprise object had been created and registered. 64 + 65 +* To initialize the object, the database channel invokes the method initializeObject on the editing context, which is passed down the object store hierarchy. If the editing context is nested, it passes the message to its parent editing context. If the parent editing context contains an object with a matching global ID, that object is used to initialize the object in the child editing context. 66 + 67 +Otherwise, the initializeObject invocation is forwarded down to the editing context's EODatabaseContext, which initializes the new instance from the appropriate snapshot and creates faults for its relationships. initializeObject in EODatabaseContext sets the values of the newly instantiated enterprise object's properties using takeStoredValueForKey. 68 + 69 +* The database channel invokes awakeFromFetch on the new enterprise object. Custom enterprise object classes can override this method to perform additional initialization after an object has been created from a database row and initialized with database values. 70 + 71 +=== Enterprise Object Initialization === 72 + 73 +The following sequence of events occurs when an object is fetched from the database: 74 + 75 +* A database row is fetched as raw binary data. 76 + 77 +* The values retrieved from that row are converted from their database-specific types to instances of standard value classes. A sample mapping of this conversion appears in Table 6-1. An application's EOModel specifies the mapping from external data types (database type) to internal data types (Java value type). 78 + 79 +* Once the data has been converted to objects, these objects are put in an NSDictionary. The elements of the dictionary correspond to columns in the database table: Their names are the names of the attributes they map to in the EOModel and their values are the values retrieved from the database. 80 + 81 +The dictionary provides a snapshot of the database row and is eventually used to initialize an enterprise object. This snapshot also participates in optimistic locking. 82 + 83 +The dictionary contains an entry for all of a row's columns, but an enterprise object initialized from the dictionary contains only the attributes that are defined as class properties or client-side class properties in the entity's EOModel. 84 + 85 +* A new enterprise object is instantiated by an EOEntityClassDescription object. 86 + 87 +* The enterprise object is initialized from a row snapshot. Only objects that are class properties or client-side 88 +class properties are included. Faults are created for any references to relationships defined in the EOModel. 89 + 7 7 == Locking == 8 8 9 9 == Data Freshness ==