Esempio n. 1
0
        /// <summary>
        /// Effective implementation of the Export.
        /// </summary>
        private void Export(ISimpleTaskHost host, ExportAction initialAction, List <DataRelation> relationsToAdd)
        {
            // Create action queue and seed with initialAction:
            var actionQueue = new ExportActionsQueue();

            actionQueue.Enqueue(initialAction);

            // Run over all actions in queue:
            while (actionQueue.Count > 0)
            {
                // Get next action:
                var action = actionQueue.Dequeue();

                // Host handling:
                if (host.IsAbortRequested)
                {
                    host.Aborting(); return;
                }
                host.Out.WriteLine("  FROM {0} WHERE {1} [{2}]", action.Table, action.Where, (action.Parameters == null) ? "" : String.Join(", ", action.Parameters));

                // Retrieve or Create table definition on dataset:
                var dsTableName = action.Table.SchemaDotName;
                var dsTable     = (DataTable)null;
                if (TargetDataSet.Tables.Contains(dsTableName))
                {
                    // Retrieve table:
                    dsTable = TargetDataSet.Tables[dsTableName];
                }
                else
                {
                    // Create table:
                    Connection.FillDataSet(TargetDataSet, dsTableName, "SELECT * FROM " + action.Table.ToString() + " WHERE (1=0)", MissingSchemaAction.AddWithKey);
                    dsTable = TargetDataSet.Tables[dsTableName];

                    // Create relational constraints to tables already existing, in one direction:
                    foreach (var relation in action.Table.GetFromRelations())
                    {
                        if (TargetDataSet.Tables.Contains(relation.ForeignTable.SchemaDotName))
                        {
                            var parentCols = new List <DataColumn>();
                            foreach (var col in relation.PrimaryColumns)
                            {
                                parentCols.Add(dsTable.Columns[col.Name]);
                            }

                            var childTable = TargetDataSet.Tables[relation.ForeignTable.SchemaDotName];
                            var childCols  = new List <DataColumn>();
                            foreach (var col in relation.ForeignColumns)
                            {
                                childCols.Add(childTable.Columns[col.Name]);
                            }

                            relationsToAdd.Add(new DataRelation(relation.SchemaDotName, parentCols.ToArray(), childCols.ToArray()));
                        }
                    }
                    // and in the other direction:
                    foreach (var relation in action.Table.GetToRelations())
                    {
                        if (TargetDataSet.Tables.Contains(relation.PrimaryTable.SchemaDotName))
                        {
                            var parentTable = TargetDataSet.Tables[relation.PrimaryTable.SchemaDotName];
                            if (dsTable == parentTable)
                            {
                                continue;
                            }
                            var parentCols = new List <DataColumn>();
                            foreach (var col in relation.PrimaryColumns)
                            {
                                parentCols.Add(parentTable.Columns[col.Name]);
                            }

                            var childCols = new List <DataColumn>();
                            foreach (var col in relation.ForeignColumns)
                            {
                                childCols.Add(dsTable.Columns[col.Name]);
                            }

                            relationsToAdd.Add(new DataRelation(relation.SchemaDotName, parentCols.ToArray(), childCols.ToArray()));
                        }
                    }
                }

                // Construct SQL query for export:
                var sql = "SELECT * FROM " + action.Table.ToString() + " WHERE (" + action.Where + ")";

                // Append filters (if any):
                foreach (var filter in this.TableFilters.Where(f => f.Key == action.Table))
                {
                    sql += " AND (" + filter.Value + ")";
                }

                using (var cmd = Connection.CreateCommand(sql))
                {
                    // Add system query parameters (if any):
                    if (action.Parameters != null && action.Parameters.Length > 0)
                    {
                        for (int i = 0; i < action.Parameters.Length; i++)
                        {
                            cmd.AddParameter("@p" + i, action.Parameters[i]);
                        }
                    }

                    // Add user query parameters (if any) (only on root queries, where action.Parameters = null):
                    if (action.Parameters == null)
                    {
                        foreach (var item in this.QueryArguments)
                        {
                            if (!sql.Contains(item.Key))
                            {
                                continue;                          // Skip arguments that do not appear in sql.
                            }
                            cmd.AddParameter(item.Key, item.Value);
                        }
                    }

                    // Execute the query:
                    using (var reader = cmd.ExecuteReader())
                    {
                        // Construct a map of columns:
                        var map = (DataReaderMap)null;
                        map = new DataReaderMap(reader);

                        // Iterate over all returned rows:
                        while (reader.Read())
                        {
                            // Retrieve row values:
                            var values = new object[reader.FieldCount];
                            reader.GetValues(values);

                            try
                            {
                                // Add row to dataset:
                                var dataRow = TargetDataSet.Tables[dsTableName].Rows.Add(values);

                                // Enqueue related child rows for export (except if excluded):
                                foreach (var rel in action.Table.GetFromRelations())
                                {
                                    if ((this.ExportMode == DbExportMode.None) && (!this.RelationsToInclude.Contains(rel)))
                                    {
                                        continue;
                                    }
                                    if (this.RelationsToExclude.Contains(rel))
                                    {
                                        continue;
                                    }

                                    var vs = new object[rel.ForeignColumns.Count];
                                    var wh = "(" + String.Join(") AND (", Enumerate.FromTo(0, rel.ForeignColumns.Count - 1).Select(i => "[" + rel.ForeignColumns[i].Name + "] = @p" + i).ToArray()) + ")";
                                    for (int i = 0; i < rel.ForeignColumns.Count; i++)
                                    {
                                        vs[i] = values[map.ColumnIndexes[rel.PrimaryColumns[i].Name]];
                                    }
                                    actionQueue.Enqueue(new ExportAction()
                                    {
                                        Table = rel.ForeignTable, Where = wh, Parameters = vs
                                    });
                                }

                                // Enqueue related parent rows for export (if in Full mode or relation explicitely included):
                                foreach (var rel in action.Table.GetToRelations())
                                {
                                    if ((this.ExportMode != DbExportMode.Full) && (!this.RelationsToInclude.Contains(rel)))
                                    {
                                        continue;
                                    }
                                    if (this.RelationsToExclude.Contains(rel))
                                    {
                                        continue;
                                    }

                                    var vs = new object[rel.PrimaryColumns.Count];
                                    var wh = "(" + String.Join(") AND (", Enumerate.FromTo(0, rel.PrimaryColumns.Count - 1).Select(i => "[" + rel.PrimaryColumns[i].Name + "] = @p" + i).ToArray()) + ")";
                                    for (int i = 0; i < rel.PrimaryColumns.Count; i++)
                                    {
                                        vs[i] = values[map.ColumnIndexes[rel.ForeignColumns[i].Name]];
                                    }
                                    actionQueue.Enqueue(new ExportAction()
                                    {
                                        Table = rel.PrimaryTable, Where = wh, Parameters = vs
                                    });
                                }
                            }
                            catch (System.Data.ConstraintException)
                            {
                                // Ignore primary key violation: record was already present...
                            }
                        }
                    }
                }
            }
        }