Hi Chuck,
thanks again for your efforts.
>> 1. The data are inserted into the temporary table from the users >> session and editing context.
> I think that is the start of your problem. What exactly are you doing?
Basically I'm developing a reporting tool for generating reports (PDF, CSV, Excel, etc.) based on data coming out of a database.
A report is generated as follows:
1.
The user selects data. This happens on one of many search interfaces provided by the application (it's a ERP System). The selected data are fetched and either displayed on the user interface with the possibility to generate a report, or a report configuration window is shown directly (this configuration window is shown in every case before generating a report).
The data that are fetched, are not stored permanently in the database in every case. It may be the case, that these data previously have been inserted into a temporary table (e.g. by a stored procedure) and are available for the report generation only.
2.
On the report configuration page, the user may select some predefined attributes and relationships available for the report, create report templates and so on. The available attributes and relationships are arranged by an admin, who has the possibility to travel along the whole object graph available based on a root entity.
3.
For generating a report, a thread is created and the already fetched data as well as other report options are passed to this thread (happens in the constructor).
4.
The thread migrates the received data into its own editing context by faulting for the objects global id.
5.
The thread begins to handle all objects by processing the object graph using reflection.
---
An Example not working for data whose source is a temporary table (reduced to the basics):
# SEARCH ACTION (returning a report configuration window)
#
public WOComponent searchAction() { NSMutableDictionary storedProcDict = new NSMutableDictionary(); storedProcDict.setObjectForKey(someValue, "someKey"); ... // fill the temporary table EOUtilities.executeStoredProcedureNamed(editingContext, "fillTempTable", storedProcDict); ...
// fetch data from temporary table EOFetchSpecification fetchSpecification = new EOFetchSpecification("tempTable", null, null); NSArray results = editingContext.objectsWithFetchSpecification(fetchSpecification);
// create and return the report configuration page (pop-up) ReportConfigurationPage page = (ReportConfigurationPage)pageWithName("ReportConfigurationPage"); page.setRootEntity("TempTableObject"); page.setModuleDescription("Some Module Name"); page.setReportName("SomeReportName"); page.setArrayWithFetchedObjects(results); // the results are migrated into the threads editing context in the threads constructor page.setMigrateFromTempTable(true); return (WOComponent)page; }
# On the report configuration window, the user selects the attributes that shall be displayed on the report and finally starts the report generation (creates a thread)
# THREAD CONSTRUCTOR
#
public ReportThread(NSArray arrayWithFetchedObjects, Report report, String reportName, ReportTemplate selectedTemplate, NSDictionary titleDict, boolean migrateFromTempTable) { ... this.arrayWithFetchedObjects = XTEditingContext.migrate(arrayWithFetchedObjects); // right here the migration is done which fails (only null values after migration) when passing data with a temporary table as source ... }
# MIGRATION
#
/** Moves database objects in an array into another editing context */ public final static NSArray migrate(NSArray anArray, EOEditingContext newEditingContext) { NSMutableArray returnArray = new NSMutableArray(); Enumeration enumerator = anArray.objectEnumerator(); while (enumerator.hasMoreElements()) { EOEnterpriseObject anEOEnterpriseObject = (EOEnterpriseObject)enumerator.nextElement(); returnArray.addObject(migrate(anEOEnterpriseObject, newEditingContext)); } return returnArray.immutableClone(); } /** Moves database object into another editing context */ public final static EOEnterpriseObject migrate(EOEnterpriseObject enterpriseObject, EOEditingContext newEditingContext) { EOEnterpriseObject result = enterpriseObject;
// is there an object? if(enterpriseObject != null) { // old editing context EOEditingContext oldEditingContext = enterpriseObject.editingContext();
// only if object is in editing context and object is already not in // the new editing Context if(oldEditingContext != null && oldEditingContext != newEditingContext) { // get global ID of the object EOGlobalID globalID = oldEditingContext.globalIDForObject(enterpriseObject);
// if the object has a global id if(globalID != null) // object with global id return to the editing context result = newEditingContext.faultForGlobalID(globalID, newEditingContext); } } return result; }
---
Andri
|