コード例 #1
0
        private bool DeleteRelated(string target)
        {
            string[]      files  = ExpressUtility.GetRelatedFiles(target);
            List <string> delete = new List <string>();

            foreach (string f in files)
            {
                if (File.Exists(f))
                {
                    delete.Add(f);
                }
            }

            if (delete.Count > 0)
            {
                if (this.Confirm("Express Bulk Copy",
                                 string.Format("The following files will be deleted along with the shape file: {0}\n\n{1}\n\nAre you sure you want to continue?",
                                               target,
                                               string.Join("\n", delete.ToArray()))))
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #2
0
        public void TestConnection()
        {
            FdoProviderInfo provider = _view.SelectedProvider;
            string          connStr  = ExpressUtility.ConvertFromNameValueCollection(_view.ConnectProperties);

            FdoConnection conn = new FdoConnection(provider.Name, connStr);

            try
            {
                FdoConnectionState state = conn.Open();
                if (state == FdoConnectionState.Open || state == FdoConnectionState.Pending)
                {
                    _view.ShowMessage(null, "Test successful");
                    conn.Close();
                }
                else
                {
                    _view.ShowError("Connection test failed");
                }
            }
            catch (FdoException ex)
            {
                _view.ShowError(ex.InnerException.Message);
            }
            finally
            {
                conn.Dispose();
            }
        }
コード例 #3
0
        public void CopySpatialContexts()
        {
            List <SpatialContextInfo> contexts   = new List <SpatialContextInfo>();
            FdoConnection             srcConn    = _connMgr.GetConnection(_view.SourceConnectionName);
            FdoConnection             targetConn = _connMgr.GetConnection(_view.SelectedTargetConnectionName);

            using (FdoFeatureService service = srcConn.CreateFeatureService())
            {
                foreach (string ctxName in _view.SpatialContexts)
                {
                    SpatialContextInfo sc = service.GetSpatialContext(ctxName);
                    if (sc != null)
                    {
                        contexts.Add(sc);
                    }
                }
            }

            if (contexts.Count == 0)
            {
                _view.ShowMessage(null, ResourceService.GetString("MSG_NO_SPATIAL_CONTEXTS_COPIED"));
                return;
            }

            ExpressUtility.CopyAllSpatialContexts(contexts, targetConn, _view.Overwrite);
            _view.ShowMessage(null, ResourceService.GetString("MSG_SPATIAL_CONTEXTS_COPIED"));
            _view.Close();
        }
コード例 #4
0
        public override int Execute()
        {
            CommandStatus retCode = CommandStatus.E_OK;

            bool create = ExpressUtility.CreateFlatFileDataSource(_file);

            if (!create)
            {
                WriteLine("Failed to create file {0}", _file);
                retCode = CommandStatus.E_FAIL_CREATE_DATASTORE;
                return((int)retCode);
            }
            WriteLine("File {0} created", _file);
            if (_schema != null)
            {
                try
                {
                    FdoConnection conn = ExpressUtility.CreateFlatFileConnection(_file);
                    conn.Open();
                    using (FdoFeatureService service = conn.CreateFeatureService())
                    {
                        service.LoadSchemasFromXml(_schema);
                        WriteLine("Schema applied to {0}", _file);
                    }
                    retCode = CommandStatus.E_OK;
                }
                catch (Exception ex)
                {
                    WriteException(ex);
                    retCode = CommandStatus.E_FAIL_APPLY_SCHEMA;
                }
            }
            return((int)retCode);
        }
コード例 #5
0
        public bool CreateSqlite()
        {
            if (_view.CreateConnection && string.IsNullOrEmpty(_view.ConnectionName))
            {
                _view.ShowError("Specify a connection name");
                return(false);
            }

            if (ExpressUtility.CreateFlatFileDataSource("OSGeo.SQLite", _view.SQLiteFile))
            {
                FdoConnection conn = ExpressUtility.CreateFlatFileConnection("OSGeo.SQLite", _view.SQLiteFile);
                if (FileService.FileExists(_view.FeatureSchemaDefinition))
                {
                    conn.Open();
                    using (FdoFeatureService service = conn.CreateFeatureService())
                    {
                        service.LoadSchemasFromXml(_view.FeatureSchemaDefinition, _view.FixIncompatibilities);
                    }
                }
                if (_view.CreateConnection)
                {
                    _connMgr.AddConnection(_view.ConnectionName, conn);
                }
                else
                {
                    conn.Dispose();
                }
            }
            return(true);
        }
コード例 #6
0
        public override void Run()
        {
            string file = FileService.OpenFile(Res.GetString("TITLE_CONNECT_SQLITE"), Res.GetString("FILTER_SQLITE"));

            if (FileService.FileExists(file))
            {
                FdoConnection        conn  = ExpressUtility.CreateFlatFileConnection("OSGeo.SQLite", file);
                FdoConnectionManager mgr   = ServiceManager.Instance.GetService <FdoConnectionManager>();
                NamingService        namer = ServiceManager.Instance.GetService <NamingService>();

                string name = Msg.ShowInputBox(Res.GetString("TITLE_CONNECTION_NAME"), Res.GetString("PROMPT_ENTER_CONNECTION"), namer.GetDefaultConnectionName("OSGeo.SQLite"));
                if (name == null)
                {
                    return;
                }

                while (name == string.Empty || mgr.NameExists(name))
                {
                    Msg.ShowError(Res.GetString("ERR_CONNECTION_NAME_EMPTY_OR_EXISTS"));
                    name = Msg.ShowInputBox(Res.GetString("TITLE_CONNECTION_NAME"), Res.GetString("PROMPT_ENTER_CONNECTION"), name);

                    if (name == null)
                    {
                        return;
                    }
                }
                mgr.AddConnection(name, conn);
            }
        }
コード例 #7
0
ファイル: TableToFlatFile.cs プロジェクト: beritec/fdotoolbox
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected override void Initialize()
        {
            SendMessage("Creating target data source");
            if (!ExpressUtility.CreateFlatFileDataSource(_outputFile))
            {
                throw new FdoETLException(ResourceUtil.GetStringFormatted("ERR_CANNOT_CREATE_DATA_FILE", _outputFile));
            }

            _outConn = ExpressUtility.CreateFlatFileConnection(_outputFile);
            _outConn.Open();

            ClassDefinition cd = _table.CreateClassDefinition(true);

            using (FdoFeatureService service = _outConn.CreateFeatureService())
            {
                SendMessage("Applying schema to target");
                FeatureSchema schema = new FeatureSchema("Schema1", "Default schema");
                schema.Classes.Add(cd);
                service.ApplySchema(schema);
            }

            SendMessage("Copying any attached spatial contexts");
            ExpressUtility.CopyAllSpatialContexts(_table.SpatialContexts, _outConn, true);

            Register(new FdoFeatureTableInputOperation(_table));
            Register(new FdoOutputOperation(_outConn, cd.Name));
        }
コード例 #8
0
        private string GenerateFilter(FdoFeature feat)
        {
            FdoFeatureTable table = feat.Table;

            if (table.PrimaryKey.Length > 0)
            {
                List <string> filters = new List <string>();
                foreach (DataColumn col in table.PrimaryKey)
                {
                    DataType dt = ExpressUtility.GetFdoDataTypeFromClrType(col.DataType);
                    string   f  = string.Empty;
                    if (dt == DataType.DataType_DateTime || dt == DataType.DataType_String)
                    {
                        f = col.ColumnName + " = '" + feat[col] + "'";
                    }
                    else
                    {
                        f = col.ColumnName + " = " + feat[col];
                    }

                    filters.Add(f);
                }
                return("(" + string.Join(" AND ", filters.ToArray()) + ")");
            }
            return(null);
        }
コード例 #9
0
ファイル: FdoDataStoreCtrl.cs プロジェクト: morkl/fdotoolbox
        private bool ExportToFile(string provider, string file, int maxSchemas, int maxSpatialContexts)
        {
            var conf = _context.GetConfiguration();

            if (maxSchemas > 0 && conf.Schemas.Count > maxSchemas)
            {
                ShowError("This provider only allows " + maxSchemas + " feature schema(s)");
                return(false);
            }
            if (maxSpatialContexts > 0 && conf.SpatialContexts.Length > maxSpatialContexts)
            {
                ShowError("This provider only allows " + maxSpatialContexts + " spatial context(s)");
                return(false);
            }

            if (ExpressUtility.CreateFlatFileDataSource(provider, file))
            {
                var conn   = ExpressUtility.CreateFlatFileConnection(provider, file);
                var schema = conf.Schemas[0];
                schema = FdoSchemaUtil.CloneSchema(schema, true);
                using (var svc = conn.CreateFeatureService())
                {
                    IncompatibleSchema incs;
                    if (!svc.CanApplySchema(schema, out incs))
                    {
                        string msg = "This schema has incompatibilities. Attempt to fix it? " + incs.ToString();
                        if (!WrappedMessageBox.Confirm("Incompatible schema", msg, MessageBoxText.YesNo))
                        {
                            return(false);
                        }
                        schema = svc.AlterSchema(schema, incs);
                    }

                    using (var cur = new TempCursor(Cursors.WaitCursor))
                    {
                        foreach (var sc in conf.SpatialContexts)
                        {
                            svc.CreateSpatialContext(sc, true);
                        }

                        //Only for SQLite, but this is general enough
                        var fscs = svc.DescribeSchema();
                        if (fscs.Count == 1)
                        {
                            var fsc = fscs[0];
                            foreach (ClassDefinition cls in schema.Classes)
                            {
                                var klass = FdoSchemaUtil.CloneClass(cls);
                                fsc.Classes.Add(klass);
                            }
                            schema = fsc;
                        }
                        svc.ApplySchema(schema);
                    }
                }
                conn.Close();
            }
            return(true);
        }
コード例 #10
0
        public void TestStringToNvc()
        {
            string str = "Username=Foo;Password=Bar;Service=localhost";
            NameValueCollection nvc = ExpressUtility.ConvertFromString(str);

            Assert.AreEqual(nvc["Username"], "Foo");
            Assert.AreEqual(nvc["Password"], "Bar");
            Assert.AreEqual(nvc["Service"], "localhost");
        }
コード例 #11
0
ファイル: FdoFeatureReader.cs プロジェクト: morkl/fdotoolbox
        internal FdoFeatureReader(IFeatureReader reader) : base(reader)
        {
            _internalFactory = new FgfGeometryFactory();
            _classDefinition = reader.GetClassDefinition();
            _ptypes          = new Dictionary <string, FdoPropertyType>();
            _associations    = new Dictionary <string, string>();
            _ordinals        = new Dictionary <string, int>();
            _types           = new Type[_classDefinition.Properties.Count];
            _names           = new string[_classDefinition.Properties.Count];
            List <string> geoms = new List <string>();

            for (int i = 0; i < _names.Length; i++)
            {
                PropertyDefinition pd = _classDefinition.Properties[i];
                _names[i] = pd.Name;
                string name = _names[i];
                _ordinals.Add(_names[i], i);

                DataPropertyDefinition      dp = pd as DataPropertyDefinition;
                GeometricPropertyDefinition gp = pd as GeometricPropertyDefinition;
                if (dp != null)
                {
                    _types[i]     = ExpressUtility.GetClrTypeFromFdoDataType(dp.DataType);
                    _ptypes[name] = ValueConverter.FromDataType(dp.DataType);
                }
                else if (gp != null)
                {
                    _types[i] = typeof(byte[]);
                    geoms.Add(gp.Name);
                    _ptypes[name]       = FdoPropertyType.Geometry;
                    _associations[name] = gp.SpatialContextAssociation;
                }
                else if (pd.PropertyType == PropertyType.PropertyType_ObjectProperty)
                {
                    _ptypes[name] = FdoPropertyType.Object;
                }
                else if (pd.PropertyType == PropertyType.PropertyType_RasterProperty)
                {
                    _ptypes[name] = FdoPropertyType.Raster;
                    _types[i]     = typeof(IRaster);
                }
                else if (pd.PropertyType == PropertyType.PropertyType_AssociationProperty)
                {
                    _ptypes[name] = FdoPropertyType.Association;
                }
            }
            _geometryNames = geoms.ToArray();
            if (_classDefinition is FeatureClass && (_classDefinition as FeatureClass).GeometryProperty != null)
            {
                _defaultGeometryName = (_classDefinition as FeatureClass).GeometryProperty.Name;
            }
            else if (geoms.Count > 0)
            {
                _defaultGeometryName = geoms[0];
            }
        }
コード例 #12
0
        public void TestCreateFlatFile()
        {
            Assert.IsTrue(ExpressUtility.CreateFlatFileDataSource("Test.sdf"));
            Assert.IsTrue(ExpressUtility.CreateFlatFileDataSource("Test.sqlite"));
            Assert.IsTrue(ExpressUtility.CreateFlatFileDataSource("Test.db"));

            File.Delete("Test.sdf");
            File.Delete("Test.sqlite");
            File.Delete("Test.db");
        }
コード例 #13
0
        public void TestNvcToString()
        {
            NameValueCollection nvc = new NameValueCollection();

            nvc["Username"] = "******";
            nvc["Password"] = "******";
            nvc["Service"]  = "localhost";
            string str = ExpressUtility.ConvertFromNameValueCollection(nvc);

            Assert.AreEqual(str, "Username=Foo;Password=Bar;Service=localhost");
        }
コード例 #14
0
        /// <summary>
        /// Creates a <see cref="ClassDefinition"/> from this instance
        /// </summary>
        /// <param name="createAutoGeneratedId">If true, will add an auto-generated id property to this class definition</param>
        /// <returns>The class definition</returns>
        public ClassDefinition CreateClassDefinition(bool createAutoGeneratedId)
        {
            ClassDefinition cd = null;

            if (!string.IsNullOrEmpty(this.GeometryColumn))
            {
                FeatureClass fc = new FeatureClass(this.TableName, string.Empty);
                GeometricPropertyDefinition gp = new GeometricPropertyDefinition(this.GeometryColumn, string.Empty);
                fc.Properties.Add(gp);
                fc.GeometryProperty = gp;
                cd = fc;
            }
            else
            {
                cd = new Class(this.TableName, string.Empty);
            }

            if (createAutoGeneratedId)
            {
                int    num     = 1;
                string name    = "AutoID";
                string genName = name + num;
                string theName = string.Empty;
                if (this.Columns[name] != null)
                {
                    while (this.Columns[genName] != null)
                    {
                        genName = name + (num++);
                    }
                    theName = genName;
                }
                else
                {
                    theName = name;
                }

                DataPropertyDefinition id = new DataPropertyDefinition(theName, string.Empty);
                id.IsAutoGenerated = true;
                id.DataType        = DataType.DataType_Int32;
                cd.Properties.Add(id);
                cd.IdentityProperties.Add(id);
            }

            //Now process columns
            foreach (DataColumn dc in this.Columns)
            {
                if (dc.ColumnName != this.GeometryColumn)
                {
                    DataPropertyDefinition dp = ExpressUtility.GetDataPropertyForColumn(dc);
                    cd.Properties.Add(dp);
                }
            }
            return(cd);
        }
コード例 #15
0
        public void Init(string initSchema, string initClass)
        {
            List <QueryMode> modes = new List <QueryMode>();

            if (!string.IsNullOrEmpty(initSchema) && !string.IsNullOrEmpty(initClass))
            {
                if (_service.SupportsCommand(OSGeo.FDO.Commands.CommandType.CommandType_Select))
                {
                    using (FdoFeatureService service = _connection.CreateFeatureService())
                    {
                        ClassDefinition classDef = service.GetClassByName(initSchema, initClass);
                        if (!ExpressUtility.HasRaster(classDef))
                        {
                            modes.Add(QueryMode.Standard);
                            _queryViews.Add(QueryMode.Standard, new FdoStandardQueryCtl(_connection, initSchema, initClass));
                        }
                    }
                }
                if (_service.SupportsCommand(OSGeo.FDO.Commands.CommandType.CommandType_SelectAggregates))
                {
                    modes.Add(QueryMode.Aggregate);
                    _queryViews.Add(QueryMode.Aggregate, new FdoAggregateQueryCtl(_connection, initSchema, initClass));
                }
            }
            else
            {
                if (_service.SupportsCommand(OSGeo.FDO.Commands.CommandType.CommandType_Select))
                {
                    modes.Add(QueryMode.Standard);
                    _queryViews.Add(QueryMode.Standard, new FdoStandardQueryCtl(_connection));
                }
                if (_service.SupportsCommand(OSGeo.FDO.Commands.CommandType.CommandType_SelectAggregates))
                {
                    modes.Add(QueryMode.Aggregate);
                    _queryViews.Add(QueryMode.Aggregate, new FdoAggregateQueryCtl(_connection));
                }
            }
            if (_service.SupportsCommand(OSGeo.FDO.Commands.CommandType.CommandType_SQLCommand))
            {
                modes.Add(QueryMode.SQL);
                _queryViews.Add(QueryMode.SQL, new FdoSqlQueryCtl());
            }
            foreach (IQuerySubView qv in _queryViews.Values)
            {
                qv.MapPreviewStateChanged += new MapPreviewStateEventHandler(OnMapPreviewStateChanged);
                qv.SetRestrictions(_connection.Capability);
            }
            _view.QueryModes = modes;

            _view.InsertEnabled = (_view.SelectedQueryMode != QueryMode.SQL) && insertSupported;
        }
コード例 #16
0
        internal FdoSqlReader(ISQLDataReader reader)
        {
            _internalReader = reader;
            _ordinals       = new Dictionary <string, int>();
            int count = reader.GetColumnCount();

            _types  = new Type[count];
            _names  = new string[count];
            _ptypes = new Dictionary <string, FdoPropertyType>();
            List <string> geoms = new List <string>();

            for (int i = 0; i < count; i++)
            {
                string name = _internalReader.GetColumnName(i);
                _names[i] = name;
                _ordinals.Add(name, i);

                PropertyType ptype = _internalReader.GetPropertyType(name);
                if (ptype == PropertyType.PropertyType_DataProperty)
                {
                    _types[i]     = ExpressUtility.GetClrTypeFromFdoDataType(_internalReader.GetColumnType(name));
                    _ptypes[name] = ValueConverter.FromDataType(_internalReader.GetColumnType(name));
                }
                else if (ptype == PropertyType.PropertyType_GeometricProperty)
                {
                    _types[i] = typeof(byte[]);
                    geoms.Add(name);
                    _ptypes[name] = FdoPropertyType.Geometry;
                }
                else if (ptype == PropertyType.PropertyType_AssociationProperty)
                {
                    _ptypes[name] = FdoPropertyType.Association;
                }
                else if (ptype == PropertyType.PropertyType_ObjectProperty)
                {
                    _ptypes[name] = FdoPropertyType.Object;
                }
                else if (ptype == PropertyType.PropertyType_RasterProperty)
                {
                    _ptypes[name] = FdoPropertyType.Raster;
                }
            }
            _geometryNames = geoms.ToArray();
            if (geoms.Count > 0)
            {
                _defaultGeometryName = geoms[0];
            }
        }
コード例 #17
0
 private void DeleteRelatedFiles(string shp)
 {
     string[] files = ExpressUtility.GetRelatedFiles(shp);
     foreach (string f in files)
     {
         if (File.Exists(f))
         {
             File.Delete(f);
             LoggingService.Info("File deleted: " + f);
         }
     }
     if (File.Exists(shp))
     {
         File.Delete(shp);
     }
 }
コード例 #18
0
        private void btnOK_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtSavePath.Text))
            {
                MessageService.ShowError("Please specify a file name to save to");
                return;
            }
            string provider = rdSdf.Checked ? "OSGeo.SDF" : "OSGeo.SQLite";

            using (FdoBulkCopy bcp = ExpressUtility.CreateBulkCopy(_source, _schemaName, _className, provider, txtSavePath.Text))
            {
                EtlProcessCtl ctl = new EtlProcessCtl(bcp);
                Workbench.Instance.ShowContent(ctl, ViewRegion.Dialog);
                this.Close();
            }
        }
コード例 #19
0
        private void btnExecute_Click(object sender, EventArgs e)
        {
            string source = txtSource.Text;
            string target = txtTarget.Text;

            if (FileService.FileExists(source) && !string.IsNullOrEmpty(target))
            {
                if (ExpressUtility.IsShp(target))
                {
                    if (File.Exists(target))
                    {
                        if (!DeleteRelated(target))
                        {
                            return;
                        }
                        else
                        {
                            DeleteRelatedFiles(target);
                        }
                    }
                    else if (Directory.Exists(target))
                    {
                        string shp = Path.Combine(target, Path.GetFileNameWithoutExtension(source) + ".shp");
                        if (File.Exists(shp) && !DeleteRelated(shp))
                        {
                            return;
                        }
                        else
                        {
                            DeleteRelatedFiles(shp);
                        }
                    }
                }

                using (FdoBulkCopy bcp = ExpressUtility.CreateBulkCopy(source, target, chkCopySpatialContexts.Checked, true, chkFlatten.Checked))
                {
                    EtlProcessCtl ctl = new EtlProcessCtl(bcp);
                    Workbench.Instance.ShowContent(ctl, ViewRegion.Dialog);
                    base.Close();
                }
            }
            else
            {
                this.ShowError("Source and Target fields are required");
            }
        }
コード例 #20
0
ファイル: SdfFileHandler.cs プロジェクト: beritec/fdotoolbox
        /// <summary>
        /// Handles the file drop
        /// </summary>
        /// <param name="file">The file being dropped</param>
        public void HandleDrop(string file)
        {
            IFdoConnectionManager connMgr = ServiceManager.Instance.GetService<IFdoConnectionManager>();
            NamingService namer = ServiceManager.Instance.GetService<NamingService>();
            FdoConnection conn = null;
            try
            {
                conn = ExpressUtility.CreateFlatFileConnection(file);
            }
            catch (Exception ex)
            {
                LoggingService.Error("Failed to load connection", ex);
                return;
            }

            string name = namer.GetDefaultConnectionName(conn.Provider, System.IO.Path.GetFileNameWithoutExtension(file));
            connMgr.AddConnection(name, conn);
        }
コード例 #21
0
ファイル: FdoDataStoreCtrl.cs プロジェクト: morkl/fdotoolbox
        private void btnSaveSqlite_Click(object sender, EventArgs e)
        {
            string file = FileService.SaveFile("Export to SQLite", "SQLite databases (*.sqlite)|*.sqlite|SQLite databases (*.db)|*.db");

            if (!string.IsNullOrEmpty(file))
            {
                //SQLite only allows
                // 1 feature schema
                // any number spatial contexts
                if (ExportToFile("OSGeo.SQLite", file, 1, -1))
                {
                    if (Confirm("Export", "Successfully exported to: " + file + ". Connect to it?"))
                    {
                        var connMgr = ServiceManager.Instance.GetService <FdoConnectionManager>();
                        var nameSvc = ServiceManager.Instance.GetService <NamingService>();

                        var name = nameSvc.GetDefaultConnectionName("OSGeo.SQLite", System.IO.Path.GetFileNameWithoutExtension(file));
                        var conn = ExpressUtility.CreateFlatFileConnection(file);

                        connMgr.AddConnection(name, conn);
                    }
                }
            }
        }
コード例 #22
0
            public override IEnumerable <FdoRow> Execute(IEnumerable <FdoRow> rows)
            {
                if (_counter < 1) //Shouldn't be reentrant, but just play it safe.
                {
                    /*
                     * Check and apply the following rules for all geometry properties to be created
                     *
                     * Target supports multiple spatial contexts:
                     * -------------------------------------------
                     * If there is no spatial contexts of the specified (source) name. Create a copy of the source spatial context.
                     * If there is a spatial context of the same name, using the same WKT. Do nothing
                     * If there is a spatial context of the same name, but using a different WKT. Create a new spatial context using the source WKT, but use a different name.
                     *
                     * Target only supports one spatial context:
                     * If there is no spatial context already. Create a copy of the source spatial context.
                     * If there is a spatial context of the same WKT. Change the association to match the name of this spatial context.
                     * If there is a spatial context not using the source WKT. Change the association to match the name of this spatial context. This may not be ideal, but there is no other option at this point.
                     *
                     * The regular schema compatibility fixes will handle the other properties
                     */
                    bool targetSupportsMultipleSpatialContexts      = _target.Capability.GetBooleanCapability(CapabilityType.FdoCapabilityType_SupportsMultipleSpatialContexts);
                    List <SpatialContextInfo> targetSpatialContexts = null;
                    List <SpatialContextInfo> sourceSpatialContexts = null;

                    if (typeof(CreateTargetClassFromSource).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var ct = (CreateTargetClassFromSource)_opts.PreCopyTargetModifier;

                                Info("Getting current schema from target");
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                if (schema.Classes.IndexOf(ct.Name) >= 0)
                                {
                                    Info("Class " + _opts.TargetSchema + ":" + ct.Name + " already exists. Nothing to do here");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = ssvc.GetClassByName(ct.Schema, ct.Name);
                                    Info("Creating a cloned copy of source class " + ct.Schema + ":" + ct.Name);

                                    var cloned     = FdoSchemaUtil.CloneClass(cls);
                                    var propList   = new List <string>(_opts.CheckSourceProperties);
                                    var removeList = new List <string>();
                                    foreach (PropertyDefinition prop in cloned.Properties)
                                    {
                                        string propName = prop.Name;
                                        if (!propList.Contains(propName))
                                        {
                                            removeList.Add(propName);
                                        }
                                    }

                                    if (removeList.Count > 0)
                                    {
                                        Info("Removing " + removeList.Count + " unused properties from cloned class");
                                        var props = cloned.Properties;
                                        var ids   = cloned.IdentityProperties;
                                        foreach (var name in removeList)
                                        {
                                            if (ids.Contains(name))
                                            {
                                                ids.RemoveAt(ids.IndexOf(name));
                                            }

                                            if (props.Contains(name))
                                            {
                                                props.RemoveAt(props.IndexOf(name));
                                            }
                                        }
                                        Info(removeList.Count + " unused properties removed");
                                    }

                                    foreach (var prop in ct.PropertiesToCreate)
                                    {
                                        Info("Adding property to cloned class: " + prop.Name);
                                        PropertyDefinition clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                        cloned.Properties.Add(clonedProp);
                                    }

                                    //Add an auto-generated identity property if none exist
                                    if (cloned.IdentityProperties.Count == 0)
                                    {
                                        var id = new DataPropertyDefinition("FID", "Auto-Generated Feature Id");
                                        id.IsAutoGenerated = true;
                                        id.Nullable        = false;
                                        //This may not be valid for target connection, but FdoFeatureService
                                        //will fix this for us.
                                        id.DataType = DataType.DataType_Int32;

                                        cloned.Properties.Add(id);
                                        cloned.IdentityProperties.Add(id);

                                        Info("Adding an auto-generated id (FID) to this cloned class");
                                    }

                                    Info("Checking this class for incompatibilities");
                                    IncompatibleClass ic;
                                    if (!tsvc.CanApplyClass(cloned, out ic))
                                    {
                                        Info("Altering this class to become compatible with target connection");
                                        cloned = tsvc.AlterClassDefinition(cloned, ic);
                                        Info("Class successfully altered");
                                    }

                                    Info("Checking if any spatial contexts need to be created and/or references modified");
                                    foreach (PropertyDefinition pd in cloned.Properties)
                                    {
                                        if (pd.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                        {
                                            AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)pd);
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Adding cloned class to target schema");
                                    schema.Classes.Add(cloned);
                                    Info("Applying schema back to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Updated schema applied to target connection");
                                }
                            }
                    }
                    else if (typeof(UpdateTargetClass).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        var ut = (UpdateTargetClass)_opts.PreCopyTargetModifier;
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                var cidx   = schema.Classes.IndexOf(ut.Name);
                                if (cidx < 0)
                                {
                                    throw new InvalidOperationException("Target class to be updated " + _opts.TargetSchema + ":" + ut.Name + " not found");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = schema.Classes[cidx];
                                    foreach (var prop in ut.PropertiesToCreate)
                                    {
                                        if (cls.Properties.IndexOf(prop.Name) < 0)
                                        {
                                            Info("Adding property to class: " + prop.Name);
                                            var clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                            if (clonedProp.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                            {
                                                AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)clonedProp);
                                            }
                                            cls.Properties.Add(clonedProp);
                                        }
                                        else
                                        {
                                            Info("Skipping property " + prop.Name + " because it already exists");
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Applying modified schema " + schema.Name + " to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Modified schema " + schema.Name + " applied to target connection");
                                }
                            }
                    }

                    _counter++;
                }
                return(rows);
            }
コード例 #23
0
        public bool CreateShp()
        {
            if (_view.CreateConnection && string.IsNullOrEmpty(_view.ConnectionName))
            {
                _view.ShowError("Specify a connection name");
                return(false);
            }
            //Creating SHP files is as follows
            //
            // 1. Connect to the *parent* directory of the shape file we want to create
            // 2. Apply the schema to this connection

            if (FileService.FileExists(_view.FeatureSchemaDefinition))
            {
                try
                {
                    FdoConnection             conn   = ExpressUtility.CreateFlatFileConnection("OSGeo.SHP", _view.ShpDirectory);
                    FdoDataStoreConfiguration config = FdoDataStoreConfiguration.FromFile(_view.FeatureSchemaDefinition);

                    //SHP allows the following:
                    // 1 feature schema
                    // Multiple spatial contexts
                    if (config.Schemas.Count > 1)
                    {
                        _view.ShowError("More than 1 feature schema was found in the document. SHP only allows 1 feature schema");
                        return(false);
                    }
                    var schema = config.Schemas[0];
                    using (var svc = conn.CreateFeatureService())
                    {
                        foreach (var sc in config.SpatialContexts)
                        {
                            svc.CreateSpatialContext(sc, true);
                        }

                        if (_view.FixIncompatibilities)
                        {
                            IncompatibleSchema incs;
                            if (!svc.CanApplySchema(schema, out incs))
                            {
                                schema = svc.AlterSchema(schema, incs);
                            }
                        }

                        svc.ApplySchema(schema);
                    }
                    conn.Dispose();
                    if (_view.CreateConnection)
                    {
                        conn = ExpressUtility.CreateFlatFileConnection("OSGeo.SHP", _view.ShpDirectory);
                        conn.Open();
                        _connMgr.AddConnection(_view.ConnectionName, conn);
                    }
                }
                catch (OSGeo.FDO.Common.Exception ex)
                {
                    _view.ShowError(ex);
                    LoggingService.Error("Failed to create SHP", ex);
                    return(false);
                }
            }
            return(true);
        }
コード例 #24
0
ファイル: HostApplication.cs プロジェクト: beritec/fdotoolbox
        /// <summary>
        /// Creates the fdo connection.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="name">The name.</param>
        public static void CreateFdoFileConnection(string file, string name)
        {
            FdoConnection conn = ExpressUtility.CreateFlatFileConnection(file);

            ConnectionManager.AddConnection(name, conn);
        }
コード例 #25
0
        public override int Execute()
        {
            CommandStatus retCode;

            FdoConnection srcConn  = new FdoConnection(_srcProvider, _srcConnStr);
            FdoConnection destConn = null;

            //Directory given, assume SHP
            if (Directory.Exists(_destPath))
            {
                destConn = new FdoConnection("OSGeo.SHP", "DefaultFileLocation=" + _destPath);
            }
            else
            {
                if (ExpressUtility.CreateFlatFileDataSource(_destPath))
                {
                    destConn = ExpressUtility.CreateFlatFileConnection(_destPath);
                }
                else
                {
                    throw new FdoException("Could not create data source: " + _destPath);
                }
            }

            try
            {
                srcConn.Open();
                destConn.Open();

                string srcName = "SOURCE";
                string dstName = "TARGET";

                FdoBulkCopyOptions options = new FdoBulkCopyOptions();
                options.RegisterConnection(srcName, srcConn);
                options.RegisterConnection(dstName, destConn);
                using (FdoFeatureService srcService = srcConn.CreateFeatureService())
                    using (FdoFeatureService destService = destConn.CreateFeatureService())
                    {
                        //See if spatial context needs to be copied to target
                        if (!string.IsNullOrEmpty(_srcSpatialContext))
                        {
                            SpatialContextInfo srcCtx = srcService.GetSpatialContext(_srcSpatialContext);
                            if (srcCtx != null)
                            {
                                Console.WriteLine("Copying spatial context: " + srcCtx.Name);
                                ExpressUtility.CopyAllSpatialContexts(new SpatialContextInfo[] { srcCtx }, destConn, true);
                            }
                        }
                        else
                        {
                            //Copy all
                            ExpressUtility.CopyAllSpatialContexts(srcConn, destConn, true);
                        }

                        FeatureSchema srcSchema = null;
                        //See if partial class list is needed
                        if (_srcClasses.Count > 0)
                        {
                            WriteLine("Checking if partial schema discovery is supported: " + srcService.SupportsPartialSchemaDiscovery());

                            srcSchema = srcService.PartialDescribeSchema(_srcSchema, _srcClasses);
                        }
                        else //Full copy
                        {
                            WriteLine("No classes specified, reading full source schema");
                            srcSchema = srcService.GetSchemaByName(_srcSchema);
                        }

                        if (srcSchema == null)
                        {
                            WriteError("Could not find source schema: " + _srcSchema);
                            retCode = CommandStatus.E_FAIL_SCHEMA_NOT_FOUND;
                        }
                        else
                        {
                            WriteLine("Checking source schema for incompatibilities");
                            FeatureSchema      targetSchema = null;
                            IncompatibleSchema incSchema;
                            if (destService.CanApplySchema(srcSchema, out incSchema))
                            {
                                int clsCount = srcSchema.Classes.Count;
                                WriteLine("Applying source schema (containing " + clsCount + " classes) to target");
                                destService.ApplySchema(srcSchema, null, true);
                                targetSchema = srcSchema;
                            }
                            else
                            {
                                WriteWarning("Incompatibilities were detected in source schema. Applying a modified version to target");
                                FeatureSchema fixedSchema = destService.AlterSchema(srcSchema, incSchema);
                                int           clsCount    = fixedSchema.Classes.Count;
                                WriteLine("Applying modified source schema (containing " + clsCount + " classes) to target");
                                destService.ApplySchema(fixedSchema, null, true);
                                targetSchema = fixedSchema;
                            }

                            //Now set class copy options
                            foreach (ClassDefinition cd in srcSchema.Classes)
                            {
                                FdoClassCopyOptions copt = new FdoClassCopyOptions(srcName, dstName, srcSchema.Name, cd.Name, targetSchema.Name, cd.Name);
                                copt.FlattenGeometries = _flatten;
                                options.AddClassCopyOption(copt);
                            }

                            if (_flatten)
                            {
                                WriteWarning("The switch -flatten has been defined. Geometries that are copied will have any Z or M coordinates removed");
                            }

                            FdoBulkCopy copy = new FdoBulkCopy(options);
                            copy.ProcessMessage   += new MessageEventHandler(OnMessage);
                            copy.ProcessCompleted += new EventHandler(OnCompleted);
                            Console.WriteLine("Executing bulk copy");
                            copy.Execute();
                            List <Exception> errors = new List <Exception>(copy.GetAllErrors());
                            if (errors.Count > 0)
                            {
                                string file = GenerateLogFileName("bcp-error-");
                                LogErrors(errors, file);
                                base.WriteError("Errors were encountered during bulk copy.");
                                retCode = CommandStatus.E_FAIL_BULK_COPY_WITH_ERRORS;
                            }
                            else
                            {
                                retCode = CommandStatus.E_OK;
                            }
                            retCode = CommandStatus.E_OK;
                        }
                    }
            }
            catch (Exception ex)
            {
                WriteException(ex);
                retCode = CommandStatus.E_FAIL_UNKNOWN;
            }
            finally
            {
                srcConn.Dispose();
                destConn.Dispose();
            }
            return((int)retCode);
        }
コード例 #26
0
        public bool Connect()
        {
            if (string.IsNullOrEmpty(_view.ConnectionName))
            {
                _view.FlagNameError("Required");
                return(false);
            }

            FdoConnection conn = _manager.GetConnection(_view.ConnectionName);

            if (conn != null)
            {
                _view.FlagNameError("A connection named " + _view.ConnectionName + " already exists");
                return(false);
            }

            FdoProviderInfo provider = _view.SelectedProvider;
            //string connStr = ExpressUtility.ConvertFromNameValueCollection(_view.ConnectProperties);

            NameValueCollection cp = new NameValueCollection(_view.ConnectProperties);

            if (_pendingProperties.Count > 0)
            {
                NameValueCollection extra = new NameValueCollection();
                cp.Add(extra);
            }
            string connStr = ExpressUtility.ConvertFromNameValueCollection(cp);

            conn = new FdoConnection(provider.Name, connStr);
            if (FileService.FileExists(_view.ConfigFile))
            {
                try
                {
                    conn.SetConfiguration(_view.ConfigFile);
                }
                catch (Exception ex)
                {
                    conn.Dispose();
                    _view.FlagConfigError(ex.Message);
                    return(false);
                }
            }

            try
            {
                FdoConnectionState state = conn.Open();
                if (state == FdoConnectionState.Open)
                {
                    _manager.AddConnection(_view.ConnectionName, conn);
                    return(true);
                }
                else if (state == FdoConnectionState.Pending)
                {
                    //Re-query the pending parameters and re-prompt in a new dialog
                    if (_pendingProperties.Count > 0)
                    {
                        List <DictionaryProperty> pend = new List <DictionaryProperty>();
                        foreach (DictionaryProperty p in _pendingProperties)
                        {
                            pend.Add(conn.GetConnectTimeProperty(p.Name));
                        }
                        NameValueCollection extra = PendingParameterDialog.GetExtraParameters(pend);
                        //Cancelled action
                        if (extra == null)
                        {
                            return(false);
                        }

                        cp.Add(extra);
                        conn.ConnectionString = ExpressUtility.ConvertFromNameValueCollection(cp);
                        if (conn.Open() == FdoConnectionState.Open)
                        {
                            _manager.AddConnection(_view.ConnectionName, conn);
                            return(true);
                        }
                    }
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                _view.ShowError(ex);
                conn.Dispose();
                return(false);
            }
            return(false);
        }
コード例 #27
0
        public bool CreateSdf()
        {
            if (_view.CreateConnection && string.IsNullOrEmpty(_view.ConnectionName))
            {
                _view.ShowError("Specify a connection name");
                return(false);
            }

            if (ExpressUtility.CreateFlatFileDataSource("OSGeo.SDF", _view.SdfFile))
            {
                FdoDataStoreConfiguration dstore = null;
                if (FileService.FileExists(_view.FeatureSchemaDefinition))
                {
                    dstore = FdoDataStoreConfiguration.FromFile(_view.FeatureSchemaDefinition);

                    //SDF only permits the following:
                    // 1 feature schema
                    // 1 spatial context

                    if (dstore.Schemas.Count > 1)
                    {
                        _view.ShowError("Multiple schemas were found in this document. SDF only allows 1 feature schema");
                        return(false);
                    }
                    if (dstore.SpatialContexts.Length > 1)
                    {
                        _view.ShowError("Multiple spatial contexts were found in this doucment. SDF only allows 1 spatial context");
                        return(false);
                    }
                }
                FdoConnection conn = ExpressUtility.CreateFlatFileConnection("OSGeo.SDF", _view.SdfFile);
                if (dstore != null)
                {
                    using (var svc = conn.CreateFeatureService())
                    {
                        if (dstore.SpatialContexts.Length == 1)
                        {
                            //Overwrite existing spatial context if it exists
                            var sc  = dstore.SpatialContexts[0];
                            var asc = svc.GetActiveSpatialContext();
                            if (asc != null)
                            {
                                sc.Name = asc.Name;
                            }

                            svc.CreateSpatialContext(sc, (asc != null));
                        }

                        var schema = dstore.Schemas[0];
                        if (_view.FixIncompatibilities)
                        {
                            IncompatibleSchema incS;
                            if (!svc.CanApplySchema(schema, out incS))
                            {
                                schema = svc.AlterSchema(schema, incS);
                            }
                        }
                        svc.ApplySchema(schema);
                    }
                }

                if (_view.CreateConnection)
                {
                    _connMgr.AddConnection(_view.ConnectionName, conn);
                }
                else
                {
                    conn.Dispose();
                }
            }
            return(true);
        }
コード例 #28
0
        private void btnSave_Click(object sender, EventArgs e)
        {
            var schema = _schema;

            //Remove elements that have been unchecked.
            foreach (TreeNode clsNode in treeSchema.Nodes)
            {
                string className = clsNode.Name;
                int    index     = schema.Classes.IndexOf(className);
                if (!clsNode.Checked)
                {
                    if (index >= 0)
                    {
                        schema.Classes.RemoveAt(index);
                    }
                }
                else
                {
                    if (index >= 0)
                    {
                        ClassDefinition clsDef = schema.Classes[index];
                        foreach (TreeNode propNode in clsNode.Nodes)
                        {
                            if (!propNode.Checked)
                            {
                                string propName = propNode.Text;
                                int    pidx     = clsDef.Properties.IndexOf(propName);
                                if (pidx >= 0)
                                {
                                    clsDef.Properties.RemoveAt(pidx);
                                    if (clsDef.IdentityProperties.Contains(propName))
                                    {
                                        int idpdx = clsDef.IdentityProperties.IndexOf(propName);
                                        clsDef.IdentityProperties.RemoveAt(idpdx);
                                    }
                                    if (clsDef.ClassType == ClassType.ClassType_FeatureClass)
                                    {
                                        FeatureClass fc = (FeatureClass)clsDef;
                                        if (fc.GeometryProperty.Name == propName)
                                        {
                                            fc.GeometryProperty = null;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (rdXml.Checked)
            {
                using (var ios = new IoFileStream(txtXml.Text, "w"))
                {
                    using (var writer = new XmlWriter(ios, false, XmlWriter.LineFormat.LineFormat_Indent))
                    {
                        schema.WriteXml(writer);
                        writer.Close();
                    }
                    ios.Close();
                }

                MessageService.ShowMessage("Schema saved to: " + txtXml.Text);
                this.DialogResult = DialogResult.OK;
            }
            else if (rdFile.Checked)
            {
                string fileName = txtFile.Text;
                if (ExpressUtility.CreateFlatFileDataSource(fileName))
                {
                    FdoConnection conn        = ExpressUtility.CreateFlatFileConnection(fileName);
                    bool          disposeConn = true;
                    using (FdoFeatureService svc = conn.CreateFeatureService())
                    {
                        svc.ApplySchema(schema);
                        if (MessageService.AskQuestion("Schema saved to: " + txtFile.Text + " connect to it?", "Saved"))
                        {
                            FdoConnectionManager mgr = ServiceManager.Instance.GetService <FdoConnectionManager>();
                            string name = MessageService.ShowInputBox(ResourceService.GetString("TITLE_CONNECTION_NAME"), ResourceService.GetString("PROMPT_ENTER_CONNECTION"), "");
                            if (name == null)
                            {
                                return;
                            }

                            while (name == string.Empty || mgr.NameExists(name))
                            {
                                MessageService.ShowError(ResourceService.GetString("ERR_CONNECTION_NAME_EMPTY_OR_EXISTS"));
                                name = MessageService.ShowInputBox(ResourceService.GetString("TITLE_CONNECTION_NAME"), ResourceService.GetString("PROMPT_ENTER_CONNECTION"), name);

                                if (name == null)
                                {
                                    return;
                                }
                            }
                            disposeConn = false;
                            mgr.AddConnection(name, conn);
                        }
                    }
                    if (disposeConn)
                    {
                        conn.Close();
                        conn.Dispose();
                    }
                    this.DialogResult = DialogResult.OK;
                }
            }
        }
コード例 #29
0
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected override void Initialize()
        {
            var sw = new Stopwatch();

            sw.Start();
            _options.Validate();

            SendMessage("Setting up left and right sides of the join");

            // Abstract:
            //
            // The current built-in join infrastructure is very naive as it uses nested
            // loops. Being a O(m*n) operation, the slowdown becomes readily apparent
            // as the size of the data you're working with increases. As such, the
            // current infrastructure is woefully inadequate for large datasets.
            //
            // How can we fix this problem? We could try to implement various join
            // algorithms for different scenarios, which would be a laborious exercise
            // in itself.
            //
            // Or, we can just delegate this problem to the universal swiss army-knife of
            // databases, SQLite.
            //
            // SQLite has many things going for it, including:
            //  - Support for common types of joins (important!)
            //  - LIGHTING FAST insert performance. The current FdoInputOperation is already optimised for SQLite
            //  - LIGHTING FAST read performance
            //  - Ability to use SQL to modify the database internals, such as creating indexes (FDO provider supports SQL commands)
            //
            // As such, SQLite is the perfect candidate for a temp data store to merge two
            // disparate data sources. The time spent setting up this temp SQLite database (ie. Copying "left" and
            // "right" side data into it) is negligible in the grand scheme of things.
            //
            // Process Overview:
            //
            // 1. Create temp SQLite database
            // 2. Pump left and right sides into this database
            // 3. Create indexes on join columns of both tables (IMPORTANT)
            // 4. Create a view encapsulating our join
            // 5. Copy this view out to our target
            //
            // Additional Notes:
            //
            // We will have to change our supported join types to line up with what SQLite supports, which
            // are:
            //  - INNER JOIN
            //  - LEFT OUTER JOIN
            //
            // SQLite does not support RIGHT OUTER JOINs but these could be emulated by inverting the
            // "left" and "right" tables for the LEFT OUTER JOIN. FULL OUTER JOIN is not supporte by
            // SQLite so this will be removed from our API.
            //
            // Since this SQLite database is temporary, we don't bother with putting
            // the right spatial context in there. Spatial contexts do not (should not) affect
            // the underlying coordinates of any geometries moving to and from the data store.
            //
            // SQLite views by default are represented as non-Feature classes. Geometry properties
            // default to BLOB data types. To "fix" this we need to add a new entry to the geometry_columns
            // metadata table. This may produce an incorrect feature class (ie. Has 1-n geometry properties
            // but no designated one), this is okay as we only care that the properties are there and the
            // temp-target property mappings check out.
            //
            // Although the implementation will change, the requirements remain the same, which are:
            //
            // 1. The target class must not already exist (as it will be created)
            // 2. If no designated geometry is specified, then the class definition will be FdoClass and not FdoFeatureClass

            ClassDefinition leftCls   = null;
            ClassDefinition rightCls  = null;
            ClassDefinition mergedCls = null;

            using (var leftSvc = _options.Left.Connection.CreateFeatureService())
                using (var rightSvc = _options.Right.Connection.CreateFeatureService())
                {
                    leftCls  = leftSvc.GetClassByName(_options.Left.SchemaName, _options.Left.ClassName);
                    rightCls = rightSvc.GetClassByName(_options.Right.SchemaName, _options.Right.ClassName);

                    if (leftCls == null)
                    {
                        throw new FdoETLException("Left class not found " + _options.Left.SchemaName + ":" + _options.Left.ClassName);
                    }

                    if (rightCls == null)
                    {
                        throw new FdoETLException("Right class not found " + _options.Right.SchemaName + ":" + _options.Right.ClassName);
                    }

                    var leftJoinProps  = new List <string>(_options.JoinPairs.AllKeys);
                    var rightJoinProps = new List <string>();
                    foreach (var p in leftJoinProps)
                    {
                        rightJoinProps.Add(_options.JoinPairs[p]);
                    }

                    var leftGeom  = (!string.IsNullOrEmpty(_options.GeometryProperty) && _options.Side == JoinSide.Left) ? _options.GeometryProperty : null;
                    var rightGeom = (!string.IsNullOrEmpty(_options.GeometryProperty) && _options.Side == JoinSide.Right) ? _options.GeometryProperty : null;

                    PrepareClass(leftCls, _options.LeftProperties, leftJoinProps, _options.LeftPrefix, leftGeom);
                    PrepareClass(rightCls, _options.RightProperties, rightJoinProps, _options.RightPrefix, rightGeom);

                    mergedCls = CreateMergedClass(leftCls, rightCls);
                }

            var dprops = new NameValueCollection();

            dprops["File"] = Path.GetTempFileName();

            var tempSchema = new FeatureSchema("Default", "");
            var leftCopy   = FdoSchemaUtil.CloneClass(leftCls);
            var rightCopy  = FdoSchemaUtil.CloneClass(rightCls);

            string leftClassName  = "LEFT_SIDE";
            string rightClassName = "RIGHT_SIDE";

            leftCopy.Name  = leftClassName;
            rightCopy.Name = rightClassName;

            tempSchema.Classes.Add(leftCopy);
            tempSchema.Classes.Add(rightCopy);

            //Create SQLite database
            Register(new FdoCreateDataStoreOperation("OSGeo.SQLite", dprops, null));

            //Apply temp schema
            var tempConn = new FdoConnection("OSGeo.SQLite", "File=" + dprops["File"]);

            Register(new FdoApplySchemaOperation(tempConn, tempSchema));

#if DEBUG
            Register(new FdoSingleActionOperation(() => { SendMessage("Temp db created in: " + dprops["File"]); }));
#endif

            //Prep property mappings for bulk copy
            var leftMaps  = new NameValueCollection();
            var rightMaps = new NameValueCollection();

            var leftQuery  = new FeatureQueryOptions(leftCls.Name);
            var rightQuery = new FeatureQueryOptions(rightCls.Name);

            foreach (var leftp in _options.LeftProperties)
            {
                if (string.IsNullOrEmpty(_options.LeftPrefix))
                {
                    leftMaps.Add(leftp, leftp);
                }
                else
                {
                    leftMaps.Add(leftp, _options.LeftPrefix + leftp);
                }
                leftQuery.AddFeatureProperty(leftp);
            }
            foreach (var rightp in _options.RightProperties)
            {
                if (string.IsNullOrEmpty(_options.RightPrefix))
                {
                    rightMaps.Add(rightp, rightp);
                }
                else
                {
                    rightMaps.Add(rightp, _options.RightPrefix + rightp);
                }
                rightQuery.AddFeatureProperty(rightp);
            }

            if (!string.IsNullOrEmpty(_options.LeftFilter))
            {
                leftQuery.Filter = _options.LeftFilter;
            }

            if (!string.IsNullOrEmpty(_options.RightFilter))
            {
                rightQuery.Filter = _options.RightFilter;
            }

            //don't forget join keys
            foreach (string l in _options.JoinPairs.Keys)
            {
                string r = _options.JoinPairs[l];

                if (!_options.LeftProperties.Contains(l))
                {
                    leftQuery.AddFeatureProperty(l);

                    if (string.IsNullOrEmpty(_options.LeftPrefix))
                    {
                        leftMaps.Add(l, l);
                    }
                    else
                    {
                        leftMaps.Add(l, _options.LeftPrefix + l);
                    }
                }

                if (!_options.RightProperties.Contains(r))
                {
                    rightQuery.AddFeatureProperty(r);

                    if (string.IsNullOrEmpty(_options.RightPrefix))
                    {
                        rightMaps.Add(r, r);
                    }
                    else
                    {
                        rightMaps.Add(r, _options.RightPrefix + r);
                    }
                }
            }

            //don't forget geometry!
            if (!string.IsNullOrEmpty(_options.GeometryProperty))
            {
                if (_options.Side == JoinSide.Left)
                {
                    if (!leftQuery.PropertyList.Contains(_options.GeometryProperty))
                    {
                        leftQuery.AddFeatureProperty(_options.GeometryProperty);

                        if (string.IsNullOrEmpty(_options.LeftPrefix))
                        {
                            leftMaps.Add(_options.GeometryProperty, _options.GeometryProperty);
                        }
                        else
                        {
                            leftMaps.Add(_options.GeometryProperty, _options.LeftPrefix + _options.GeometryProperty);
                        }
                    }
                }
                else
                {
                    if (!rightQuery.PropertyList.Contains(_options.GeometryProperty))
                    {
                        rightQuery.AddFeatureProperty(_options.GeometryProperty);

                        if (string.IsNullOrEmpty(_options.RightPrefix))
                        {
                            rightMaps.Add(_options.GeometryProperty, _options.GeometryProperty);
                        }
                        else
                        {
                            rightMaps.Add(_options.GeometryProperty, _options.RightPrefix + _options.GeometryProperty);
                        }
                    }
                }
            }

            var copyLeftErrors   = new List <Exception>();
            var copyRightErrors  = new List <Exception>();
            var copyTargetErrors = new List <Exception>();

            //Copy left source
            ParameterlessAction copyLeft = () =>
            {
                SendMessage("Copying left source with filter: " + _options.LeftFilter);
                var copy = ExpressUtility.CreateBulkCopy(
                    _options.Left.Connection,
                    tempConn,
                    _options.Left.SchemaName,
                    leftQuery,
                    tempSchema.Name,    //temp sqlite schema name
                    leftClassName,      //sqlite "left" class name
                    leftMaps);

                copy.ProcessMessage += delegate(object sender, MessageEventArgs e)
                {
                    SendMessage(e.Message);
                };
                copy.Execute();
                copyLeftErrors.AddRange(copy.GetAllErrors());
            };
            Register(new FdoSingleActionOperation(copyLeft));

            //Register(new FdoInputOperation(_options.Left.Connection, leftQuery));
            //Register(new FdoOutputOperation(tempConn, leftClassName, leftMaps));

            //Copy right source
            ParameterlessAction copyRight = () =>
            {
                SendMessage("Copying right source with filter: " + _options.RightFilter);
                var copy = ExpressUtility.CreateBulkCopy(
                    _options.Right.Connection,
                    tempConn,
                    _options.Right.SchemaName,
                    rightQuery,
                    tempSchema.Name,    //temp sqlite schema name
                    rightClassName,     //sqlite "right" class name
                    rightMaps);

                copy.ProcessMessage += delegate(object sender, MessageEventArgs e)
                {
                    SendMessage(e.Message);
                };
                copy.Execute();
                copyRightErrors.AddRange(copy.GetAllErrors());
            };
            Register(new FdoSingleActionOperation(copyRight));

            //Register(new FdoInputOperation(_options.Right.Connection, rightQuery));
            //Register(new FdoOutputOperation(tempConn, rightClassName, rightMaps));

            string srcClass = "VIEW_INPUT";

            //Create indexes on left and right sides to optimize read performance
            ParameterlessAction indexLeft = () =>
            {
                using (var svc = tempConn.CreateFeatureService())
                {
                    SendMessage("Creating left side index in temp db");
                    string sql    = "CREATE INDEX IDX_LEFT_ID ON " + leftClassName + "(";
                    var    tokens = new List <string>();
                    foreach (string p in _options.JoinPairs.Keys)
                    {
                        if (!string.IsNullOrEmpty(_options.LeftPrefix))
                        {
                            tokens.Add(_options.LeftPrefix + p);
                        }
                        else
                        {
                            tokens.Add(p);
                        }
                    }
                    sql = sql + string.Join(", ", tokens.ToArray()) + ")";
                    SendMessage("Executing SQL: " + sql);
                    svc.ExecuteSQLNonQuery(sql);
                }
            };
            ParameterlessAction indexRight = () =>
            {
                using (var svc = tempConn.CreateFeatureService())
                {
                    SendMessage("Creating right side index in temp db");
                    string sql    = "CREATE INDEX IDX_RIGHT_ID ON " + rightClassName + "(";
                    var    tokens = new List <string>();
                    foreach (string p in _options.JoinPairs.Keys)
                    {
                        string prop = _options.JoinPairs[p];
                        if (!string.IsNullOrEmpty(_options.RightPrefix))
                        {
                            tokens.Add(_options.RightPrefix + prop);
                        }
                        else
                        {
                            tokens.Add(prop);
                        }
                    }
                    sql = sql + string.Join(", ", tokens.ToArray()) + ")";
                    SendMessage("Executing SQL: " + sql);
                    svc.ExecuteSQLNonQuery(sql);
                }
            };
            Register(new FdoSingleActionOperation(indexLeft));
            Register(new FdoSingleActionOperation(indexRight));

            //Create view
            ParameterlessAction createView = () =>
            {
                using (var svc = tempConn.CreateFeatureService())
                {
                    SendMessage("Creating view in temp db");
                    StringBuilder sql = new StringBuilder("CREATE VIEW ");
                    sql.Append(srcClass + " AS SELECT ");
                    foreach (var p in _options.LeftProperties)
                    {
                        if (!string.IsNullOrEmpty(_options.LeftPrefix))
                        {
                            sql.Append("l." + _options.LeftPrefix + p + ", ");
                        }
                        else
                        {
                            sql.Append("l." + p + ", ");
                        }
                    }

                    if (!string.IsNullOrEmpty(_options.GeometryProperty))
                    {
                        if (_options.Side == JoinSide.Left)
                        {
                            if (!_options.LeftProperties.Contains(_options.GeometryProperty))
                            {
                                if (!string.IsNullOrEmpty(_options.LeftPrefix))
                                {
                                    sql.Append("l." + _options.LeftPrefix + _options.GeometryProperty + ", ");
                                }
                                else
                                {
                                    sql.Append("l." + _options.GeometryProperty + ", ");
                                }
                            }
                        }
                        else
                        {
                            if (!_options.RightProperties.Contains(_options.GeometryProperty))
                            {
                                if (!string.IsNullOrEmpty(_options.RightPrefix))
                                {
                                    sql.Append("r." + _options.RightPrefix + _options.GeometryProperty + ", ");
                                }
                                else
                                {
                                    sql.Append("r." + _options.GeometryProperty + ", ");
                                }
                            }
                        }
                    }

                    int rc = _options.RightProperties.Count;
                    int i  = 0;
                    foreach (var p in _options.RightProperties)
                    {
                        string pn = p;
                        if (!string.IsNullOrEmpty(_options.RightPrefix))
                        {
                            pn = _options.RightPrefix + pn;
                        }

                        if (i == rc - 1)
                        {
                            sql.Append("r." + pn + " FROM ");
                        }
                        else
                        {
                            sql.Append("r." + pn + ", ");
                        }
                        i++;
                    }
                    sql.Append(leftClassName + " l ");

                    switch (_options.JoinType)
                    {
                    case FdoJoinType.Inner:
                        sql.Append("INNER JOIN " + rightClassName + " r ON ");
                        break;

                    case FdoJoinType.Left:
                        sql.Append("LEFT OUTER JOIN " + rightClassName + " r ON ");
                        break;

                    default:
                        throw new FdoETLException("Unsupported join type: " + _options.JoinType);
                    }

                    rc = _options.JoinPairs.Count;
                    i  = 0;
                    foreach (string l in _options.JoinPairs.Keys)
                    {
                        string r = _options.JoinPairs[l];

                        string left  = l;
                        string right = r;

                        if (!string.IsNullOrEmpty(_options.LeftPrefix))
                        {
                            left = _options.LeftPrefix + left;
                        }

                        if (!string.IsNullOrEmpty(_options.RightPrefix))
                        {
                            right = _options.RightPrefix + right;
                        }

                        if (i == rc - 1)
                        {
                            sql.Append("l." + left + " = r." + right);
                        }
                        else
                        {
                            sql.Append("l." + left + " = r." + right + " AND ");
                        }

                        i++;
                    }
                    SendMessage("Executing SQL: " + sql.ToString());
                    svc.ExecuteSQLNonQuery(sql.ToString());
                }
            };
            Register(new FdoSingleActionOperation(createView));

            //Hack FDO metadata to make this a feature class
            if (!string.IsNullOrEmpty(_options.GeometryProperty))
            {
                ParameterlessAction reg = () =>
                {
                    using (var svc = tempConn.CreateFeatureService())
                    {
                        SendMessage("Exposing view as a FDO feature class");
                        string sql = "INSERT INTO geometry_columns(f_table_name, f_geometry_column, geometry_type, geometry_dettype, coord_dimension, srid, geometry_format) VALUES('" + srcClass + "','" + _options.GeometryProperty + "',15,7743,0,0,'FGF')";
                        SendMessage("Executing SQL: " + sql.ToString());
                        svc.ExecuteSQLNonQuery(sql);
                    }
                };
                Register(new FdoSingleActionOperation(reg));
            }

            //Copy view to target
            ParameterlessAction applyTarget = () =>
            {
                using (var svc = _options.Target.Connection.CreateFeatureService())
                {
                    SendMessage("Fetching target schema");
                    var schema = svc.GetSchemaByName(_options.Target.SchemaName);

                    IncompatibleClass cls;
                    if (!svc.CanApplyClass(mergedCls, out cls))
                    {
                        SendMessage("Fixing incompatibilities in merged class");
                        mergedCls = svc.AlterClassDefinition(mergedCls, cls);
                    }

                    SendMessage("Adding merged class to target schema");
                    schema.Classes.Add(mergedCls);
                    SendMessage("Applying modified target schema");
                    svc.ApplySchema(schema);
                }
            };
            Register(new FdoSingleActionOperation(applyTarget));

            var tempQuery     = new FeatureQueryOptions("VIEW_INPUT");
            var targetMapping = new NameValueCollection();
            foreach (PropertyDefinition p in mergedCls.Properties)
            {
                tempQuery.AddFeatureProperty(p.Name);
                //Target class is a replica of the temp one, so all properties
                //have the same name in both source and target
                targetMapping[p.Name] = p.Name;
            }

            ParameterlessAction copyToTarget = () =>
            {
                var copy = ExpressUtility.CreateBulkCopy(
                    tempConn,
                    _options.Target.Connection,
                    tempSchema.Name,
                    tempQuery,
                    _options.Target.SchemaName,
                    _options.Target.ClassName,
                    targetMapping);

                copy.ProcessMessage += delegate(object sender, MessageEventArgs e)
                {
                    SendMessage(e.Message);
                };
                copy.Execute();
                copyTargetErrors.AddRange(copy.GetAllErrors());
                sw.Stop();
            };
            Register(new FdoSingleActionOperation(copyToTarget));

            //Log all errors
            ParameterlessAction logErrors = () =>
            {
                SendMessage(copyLeftErrors.Count + " errors encountered copying left source to temp db");
                _allErrors.AddRange(copyLeftErrors);
                SendMessage(copyRightErrors.Count + " errors encountered copying right source to temp db");
                _allErrors.AddRange(copyRightErrors);
                SendMessage(copyTargetErrors.Count + " errors encountered copying merged source to target");
                _allErrors.AddRange(copyTargetErrors);
                SendMessage("Join Operation completed in " + sw.Elapsed.ToString());
            };
            Register(new FdoSingleActionOperation(logErrors));
        }