UpdateConnectionReferences() public method

Symbolically updates all named references to a connection with the new connection name.
public UpdateConnectionReferences ( string oldName, string newName ) : void
oldName string The old name.
newName string The new name.
return void
コード例 #1
0
ファイル: TaskLoader.cs プロジェクト: beritec/fdotoolbox
        /// <summary>
        /// Prepares the specified bulk copy definition (freshly deserialized) before the loading process begins
        /// </summary>
        /// <param name="def">The bulk copy definition.</param>
        protected override NameValueCollection Prepare(FdoToolbox.Core.Configuration.FdoBulkCopyTaskDefinition def)
        {
            /* There is subtle precondition that would've resulted in all connection references being named to a
             * single reference, thus invalidating the whole task when loaded.
             *
             * If the task definition has any connection names to an *already* loaded connection, a rename operation
             * could overwrite a previous rename operation. Consider:
             *
             * Connection A) SDF_Desktop
             * Connection B) SDFConnection0
             *
             * Loaded Connections:
             * - SDFConnection0
             * - SDFConnection1
             *
             * If during loading, SDF_Desktop matches to SDFConnection0, and SDFConnection0 matches to SDFConnection1 the rename operations
             * would then be:
             *
             * 1) Rename SDF_Desktop to SDFConnection0
             * 2) Rename SDF_Connection0 to SDFConnection1
             *
             * As a result, all referenced connections will eventually be renamed to SDFConnection1, which is not what we want.
             *
             * The solution bere is to "fix" the definition by renaming the named connections to something we know is not already a loaded
             * connection. This is done regardless to ensure consistent behaviour. Thsi method performs this solution.
             */

            string prefix  = "Connection";
            int    counter = 0;
            FdoConnectionManager connMgr = ServiceManager.Instance.GetService <FdoConnectionManager>();

            NameValueCollection nameMappings = new NameValueCollection();

            foreach (FdoConnectionEntryElement el in def.Connections)
            {
                string newName = prefix + counter;
                while (connMgr.GetConnection(newName) != null)
                {
                    counter++;
                    newName = prefix + counter;
                }
                string oldName = el.name;
                def.UpdateConnectionReferences(oldName, newName);
                nameMappings.Add(newName, oldName);
                counter++;
            }

            return(nameMappings);
        }
コード例 #2
0
        /// <summary>
        /// Loads bulk copy options from deserialized xml
        /// </summary>
        /// <param name="def">The deserialized definition.</param>
        /// <param name="name">The name.</param>
        /// <param name="owner">if set to <c>true</c> [owner].</param>
        /// <returns></returns>
        public FdoBulkCopyOptions BulkCopyFromXml(FdoBulkCopyTaskDefinition def, ref string name, bool owner)
        {
            var nameMap = Prepare(def);

            // TODO/FIXME/HACK:
            //
            // The introduction of on-the-fly schema modifications before copying has introduced a
            // potential problem which will only occur when multiple copy tasks copy to the same target
            // feature class. 
            //
            // What happens is because a target will be multiple sources copying to it, if we need
            // to create/update the target class definition, the current infrastructure will be confused
            // as to which source feature class to clone from.
            //
            // A possible solution is to return the first matching name. This will cause a "create" operation
            // to be queued. We then alter the pre-modification process so that subsequent "create" operations
            // becomes "update" operations instead.
            //
            // On second thought, the current infrastructure should be smart enought to prevent this, as
            // the UI only allows:
            //
            // 1. Mapping to an existing class
            // 2. Mapping to a class of the same name (create if necessary)
            //
            // It won't be possible to map to a class that doesn't exist, as the requirement for auto-create/update
            // is that the class name will be the same.
            //
            // ie. It won't be possible to create this mapping
            //
            // a. Foo -> Foo (create if necessary)
            // b. Bar -> Foo
            // 
            // Rule 1 prevents mapping b) from happening
            // Rule 2 ensures that Foo will only ever be created once
            //
            // If multiple sources are mapped to the same target, I believe the bcp infrastructure should ensure
            // that target must already exist first.


            name = def.name;
            Dictionary<string, FdoConnection> connections = new Dictionary<string, FdoConnection>();
            Dictionary<string, string> changeConnNames = new Dictionary<string, string>();

            //TODO: Prepare() ensured that all connections have unique names that don't already exist
            //now in the effort to re-use existing connections, see which connection entries
            //already exist and can be renamed back to the old name

            foreach (FdoConnectionEntryElement entry in def.Connections)
            {
                string connName = entry.name;
                FdoConnection conn = CreateConnection(entry.provider, entry.ConnectionString, entry.configPath, ref connName);

                connections[connName] = conn;

                if (connName != entry.name)
                {
                    changeConnNames[entry.name] = connName;
                }
            }
            
            foreach (string oldName in changeConnNames.Keys)
            {
                def.UpdateConnectionReferences(oldName, changeConnNames[oldName]);
            }

            //Compile the list of classes to be queried
            Dictionary<string, MultiSchemaQuery> queries = new Dictionary<string, MultiSchemaQuery>();
            foreach (FdoCopyTaskElement task in def.CopyTasks)
            {
                MultiSchemaQuery src = null;
                MultiSchemaQuery dst = null;

                //Process source
                if (!queries.ContainsKey(task.Source.connection))
                    src = queries[task.Source.connection] = new MultiSchemaQuery(task.Source.connection, SchemaOrigin.Source);
                else
                    src = queries[task.Source.connection];

                var sq = src.TryGet(task.Source.schema);
                if (sq != null)
                {
                    sq.AddClass(task.Source.@class);
                }
                else
                {
                    sq = new SchemaQuery(task.Source.schema);
                    sq.AddClass(task.Source.@class);
                    src.Add(sq);
                }

                //Process target
                if (!queries.ContainsKey(task.Target.connection))
                    dst = queries[task.Target.connection] = new MultiSchemaQuery(task.Target.connection, SchemaOrigin.Target);
                else
                    dst = queries[task.Target.connection];

                var tq = dst.TryGet(task.Target.schema);
                if (tq != null)
                {
                    tq.AddClass(task.Target.@class);
                }
                else
                {
                    tq = new SchemaQuery(task.Target.schema);
                    tq.AddClass(task.Target.@class);
                    dst.Add(tq);
                }
            }

            List<TargetClassModificationItem> modifiers = new List<TargetClassModificationItem>();
            using (var schemaCache = new FeatureSchemaCache())
            {
                //Now populate the schema cache with source schemas
                foreach (string connName in queries.Keys)
                {
                    if (connections.ContainsKey(connName))
                    {
                        var mqry = queries[connName];
                        var conn = connections[connName];

                        FeatureSchemaCollection schemas = new FeatureSchemaCollection(null);

                        using (var svc = conn.CreateFeatureService())
                        {
                            foreach (var sq in mqry.SchemaQueries)
                            {
                                //Source schema queries are expected to fully check out so use original method
                                if (mqry.Origin == SchemaOrigin.Source)
                                {
                                    schemas.Add(svc.PartialDescribeSchema(sq.SchemaName, new List<string>(sq.ClassNames)));
                                }
                            }
                        }

                        if (schemas.Count > 0)
                            schemaCache.Add(connName, schemas);
                    }
                }

                //Now populate the schema cache with target schemas, taking note of any
                //classes that need to be created or updated.
                foreach (string connName in queries.Keys)
                {
                    if (connections.ContainsKey(connName))
                    {
                        var mqry = queries[connName];
                        var conn = connections[connName];

                        FeatureSchemaCollection schemas = new FeatureSchemaCollection(null);

                        using (var svc = conn.CreateFeatureService())
                        {
                            foreach (var sq in mqry.SchemaQueries)
                            {
                                //Source schema queries are expected to fully check out so use original method
                                if (mqry.Origin == SchemaOrigin.Target)
                                {
                                    //Because we may need to create new classes, the old method will break down on non-existent class names
                                    //So use the new method
                                    string[] notFound;
                                    var schema = svc.PartialDescribeSchema(sq.SchemaName, new List<string>(sq.ClassNames), out notFound);
                                    //if (notFound.Length > 0)
                                    //{
                                    //    //If we can't modify schemas we'll stop right here. This is caused by elements containing createIfNotExists = true
                                    //    if (!conn.Capability.GetBooleanCapability(CapabilityType.FdoCapabilityType_SupportsSchemaModification))
                                    //        throw new NotSupportedException("The connection named " + connName + " does not support schema modification. Therefore, copy tasks and property/expression mappings cannot have createIfNotExists = true");

                                    //    //This cumbersome, but we need the parent schema name of the class that we will need to copy
                                    //    string srcSchema = GetSourceSchemaForMapping(def, sq.SchemaName, notFound);

                                    //    foreach (string className in notFound)
                                    //    {
                                    //        modifiers.Add(new CreateTargetClassFromSource(srcSchema, className));
                                    //    }
                                    //}
                                    schemas.Add(schema);
                                }
                            }
                        }

                        if (schemas.Count > 0)
                            schemaCache.Add(connName, schemas);
                    }
                }

                FdoBulkCopyOptions opts = new FdoBulkCopyOptions(connections, owner);
                
                foreach (FdoCopyTaskElement task in def.CopyTasks)
                {
                    TargetClassModificationItem mod;
                    FdoClassCopyOptions copt = FdoClassCopyOptions.FromElement(task, schemaCache, connections[task.Source.connection], connections[task.Target.connection], out mod);
                    opts.AddClassCopyOption(copt);

                    if (mod != null)
                        copt.PreCopyTargetModifier = mod;
                        //opts.AddClassModifier(mod);
                }

                return opts;
            }
        }