When FDO connects to a datastore with an existing schema and describes the schema, it maps the native data types to FDO data types to create a default physical to logical schema mapping. You can create a schema mapping that overrides the default FDO mapping. This schema override must be applied every time that you connect to the data store. Use the provider’s Schema Override API to write a program that defines the overrides and writes them to an XML configuration file. Thereafter, before opening the connection to the provider, set the connection objects’s configuration property to point to the XML configuration file.
The key elements to a schema override are an FDO feature schema and a mapping of column names in the existing table to property names in the FDO feature schema. The ODBC provider supports the mapping of two column names in an existing table to a 2D FDO point geometry property and optionally supports the mapping of three columns to a 3D point geometry property. In the event that the mapping includes an FDO geometry property, a spatial context definition should be provided.
The description given here is based on sample code written to define a schema override for a table in a Microsoft Access database. The following table shows the name of the column in the Access database, which is the same as the default FDO property name, the FDO property name assigned by the schema override, a description of the contents of the column, the FDO data type assigned by the default schema mapping, and the FDO data type assigned by the schema override.
The default schema mapping of the CITY_ID and POPULATION columns are overriden to assign them different data types than the default ones and to give them different names. A change in case counts as a change in name. The default schema mapping of the LATITUDE and LONGITUDE columns are overriden because they are combined into a single property that has a different name and a different type than the defaults. The default schema mapping of the NAME, COUNTRY, and CAPITAL columns are overriden to assign them different names than the defaults. The default schema mapping of the URL column is not overriden and retains its default type and name.
| Column Name (Default Property Name) | Override Property Name | Column Contents | Default FDO Data Type | Override FDO Data Type |
|---|---|---|---|---|
| CITY_ID | Id | consecutive sequence of integers from 1 to < 1000 | Int16 | Int64 |
| NAME | Name | Names | String | String |
| COUNTRY | Country | Names | String | String |
| CAPITAL | Captial | ‘N’ or ‘Y’ | String | String |
| URL | Not overriden | null | String | Not overriden |
| POPULATION | Population | positive integers < 17,000,000 | Double | Int32 |
| LATITUDE | Geometry | positive and negative decimals | Double | Geometry |
| LONGITUDE | Geometry | positive and negative decimals | Double | Geometry |
First a conceptual view of how to create the XML configuration file for a schema override is presented and then a code view is presented. The override includes a geometry property and so a spatial context is defined as well.
The following namespaces are used.
XmlSpatialContextFlags flags = new XmlSpatialContextFlags(); XmlSpatialContextWriter spatialContextWriter = new XmlSpatialContextWriter(writer, flags); DirectPositionImpl lowerLeft = new DirectPositionImpl(); lowerLeft.X = -180.0; lowerLeft.Y = -90.0; DirectPositionImpl upperRight = new DirectPositionImpl(); upperRight.X = 180.0; upperRight.Y = 90.0; FgfGeometryFactory geomFactory = new FgfGeometryFactory(); IEnvelope envelope = geomFactory.CreateEnvelope(lowerLeft, upperRight); IGeometry geom = geomFactory.CreateGeometry(envelope); byte[] extent = geomFactory.GetFgf(geom); spatialContextWriter.CoordinateSystem = "WGS 84"; spatialContextWriter.CoordinateSystemWkt = "GEOGCS [ \"Longitude / Latitude (WGS 84)\", DATUM [\"WGS 84\", SPHEROID [\"WGS 84\", 6378137, 298.257223563]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT \"Decimal Degree\", 0.01745329251994330]]"; spatialContextWriter.Description = "This Coordinate System is used for GPS."; spatialContextWriter.ExtentType = SpatialContextExtentType.SpatialContextExtentType_Static; spatialContextWriter.Extent = extent; spatialContextWriter.Name = "WGS84"; spatialContextWriter.XYTolerance = 0.001; // the next line writes the XML declaration, the opening tag for the fdo:DataStore element // and the gml:DerivedCRS element to the XML file spatialContextWriter.WriteSpatialContext();
FeatureSchema schema = new FeatureSchema("World", "Logical feature schema");
FeatureClass featClass = new FeatureClass("Cities", "This feature class contains one identity property, many data properties, and a feature geometry.");
PropertyDefinitionCollection properties = featClass.Properties;
DataPropertyDefinitionCollection idProperties = featClass.IdentityProperties;
DataPropertyDefinition idProp = new DataPropertyDefinition("Id", "This is the unique id number for the city.");
idProp.DataType = DataType.DataType_Int64;
idProp.IsAutoGenerated = false;
idProp.Nullable = false;
idProp.ReadOnly = true;
properties.Add(idProp);
idProperties.Add(idProp);
DataPropertyDefinition nameProp = new DataPropertyDefinition("Name", "This is the name of the City.");
nameProp.DataType = DataType.DataType_String;
nameProp.Length = 64;
properties.Add(nameProp);
DataPropertyDefinition countryProp = new DataPropertyDefinition("Country", "This is country that contains the city.");
countryProp.DataType = DataType.DataType_String;
countryProp.Length = 64;
properties.Add(countryProp);
DataPropertyDefinition populationProp = new DataPropertyDefinition("Population", "This is the population of the city.");
populationProp.DataType = DataType.DataType_Int32;
properties.Add(populationProp);
DataPropertyDefinition capitalProp = new DataPropertyDefinition("Capital", "This is 'Y' or 'N' to say whether the city is the capital of the country.");
capitalProp.DataType = DataType.DataType_String;
capitalProp.Length = 1;
properties.Add(capitalProp);
GeometricPropertyDefinition featGeomProp = new GeometricPropertyDefinition("Geometry", "This is the feature geometry.");
featGeomProp.GeometryTypes = (int)GeometricType.GeometricType_Point;
featGeomProp.HasElevation = false;
featGeomProp.HasMeasure = false;
properties.Add(featGeomProp);
featClass.GeometryProperty = featGeomProp;
ClassCollection classes = schema.Classes;
classes.Add(featClass);
// the next line writes the xs:schema element to the XML file
schema.WriteXml(writer);
// set the connection to point
// at the Microsoft Access database file
//whose Data Source Name (DSN) has been
// defined using the Data Sources (ODBC)
// Windows XP administrative tool
connection.ConnectionString = "DataSourceName=" + dataSourceName;
// get a reference to the PhysicalSchemaMapping object contained in the connection
PhysicalSchemaMapping connectionSchemaMapping = connection.CreateSchemaMapping();
// use that reference to create an override physical schema mapping
// the override definition associates columns in the columns of the Access database with property names in the FDO feature schema
OvPhysicalSchemaMapping mapping = new OvPhysicalSchemaMapping(connectionSchemaMapping, false);
mapping.Name = "World";
OvClassCollection overrideClasses = mapping.Classes;
OvClassDefinition overrrideClassDef = new OvClassDefinition("Cities");
OvPropertyDefinitionCollection overrideProperties = overrrideClassDef.Properties;
// associate the table in the Access database with the override class definition
OvTable table = new OvTable("Cities");
overrrideClassDef.Table = table;
// associate the columns in the table in the Access database with the properties in the FDO feature schema
OvColumn column = null;
OvGeometricPropertyDefinition overridGeomProp = new OvGeometricPropertyDefinition("Geometry");
overridGeomProp.GeometricColumnType = OSGeo.FDO.Providers.Rdbms.Override.OvGeometricColumnType.OvGeometricColumnType_Double;
overridGeomProp.GeometricContentType = OSGeo.FDO.Providers.Rdbms.Override.OvGeometricContentType.OvGeometricContentType_Ordinates;
overridGeomProp.XColumnName = "LONGITUDE";
overridGeomProp.YColumnName = "LATITUDE";
overrideProperties.Add(overridGeomProp);
OvDataPropertyDefinition overrideIdProp = new OvDataPropertyDefinition("Id");
column = new OvColumn("CITY_ID"); overrideIdProp.Column = column;
overrideProperties.Add(overrideIdProp);
OvDataPropertyDefinition overrideNameProp = new OvDataPropertyDefinition("Name");
column = new OvColumn("NAME");
overrideNameProp.Column = column;
overrideProperties.Add(overrideNameProp);
OvDataPropertyDefinition overrideCountryProp = new OvDataPropertyDefinition("Country");
column = new OvColumn("COUNTRY");
overrideCountryProp.Column = column;
overrideProperties.Add(overrideCountryProp);
OvDataPropertyDefinition overridePopulationProp = new OvDataPropertyDefinition("Population");
column = new OvColumn("POPULATION");
overridePopulationProp.Column = column;
overrideProperties.Add(overridePopulationProp);
OvDataPropertyDefinition overrideCapitalProp = new OvDataPropertyDefinition("Capital");
column = new OvColumn("CAPITAL");
overrideCapitalProp.Column = column;
overrideProperties.Add(overrideCapitalProp);
overrideClasses.Add(overrideClassDef);
// write the override definition to the XML file
XmlFlags flags = new XmlFlags();
// the next line writes the SchemaMapping element to the XML file
mapping.WriteXml(writer, flags);
mapping.Dispose();
The connection object contains a property whose value points to the XML configuration file.
IConnection connection = connMgr.CreateConnection(providerName);
IoFileStream configurationFileStream = new IoFileStream("Cities.xml", "r");
connection.Configuration = configurationFileStream;
connection.ConnectionString = "DataSourceName=" + dataSourceName;
connection.Open();