Example #1
0
        // only used with ADO writers
        // TODO this method can be greatly simplified
        protected internal DataSet CreateDataSetFromCursorColumns()
        {
            DataSet retval = null;

            List <TableDef> tables = GetTableInfoFromCursorColumns();
            // we have now collected all table info,
            // we can create a dataset
            DataTable dt           = null;
            DataTable primaryTable = null; //hack

            for (int i = 0; i < tables.Count; i++)
            {
                if (retval == null)
                {
                    retval = new DataSet(this._dataSourceName);
                }

                TableDef td = tables[i];

                try
                {
                    dt = retval.Tables.Add(td.Name);
                }
                catch (DuplicateNameException)
                {
                    // TODO deal with this
                    // It is a rare exception, but possible. Commence connection names are case-sensitive.
                    // In that case this exception is not thrown, but data can still end up in the wrong datatable (or more likely fail).
                    // we should probably include some pre-check and throw something more meaningful
                    throw; // for now just rethrow to be safe
                }

                // define columns
                DataColumn dc = null;

                // we need to set some general fields
                if (td.Primary)                                           // primary table columns
                {
                    dc             = dt.Columns.Add("id", typeof(Int32)); // not auto-incremented!
                    dc.AllowDBNull = false;
                    // hack for setting relations later on.
                    primaryTable = dt; // capture that this is our primary table so we can set relationships later on
                    dt.ExtendedProperties.Add("IsPrimaryTable", true);
                }
                else // related table columns
                {
                    // create a primary key that autoincrements
                    dc               = dt.Columns.Add("id", typeof(Int32));
                    dc.AllowDBNull   = false;
                    dc.AutoIncrement = true;
                    // create a foreign key field to reference the connected item
                    dc             = dt.Columns.Add("fkid", typeof(Int32));
                    dc.AllowDBNull = false; // cannot be null
                }

                // now process Commence fields
                // rest of related columns
                for (int j = 0; j < td.ColumnDefinitions.Count; j++)
                {
                    try
                    {
                        dc = dt.Columns.Add(td.ColumnDefinitions[j].FieldName);
                    }
                    catch (DuplicateNameException)
                    {
                        // appending some number would decouple the fieldname in the dataset
                        // from the fieldname in the Commence columnset.
                        // for now just rethrow
                        throw;
                    }
                    // set column properties
                    dc.DataType    = td.ColumnDefinitions[j].CommenceFieldDefinition.Type.GetTypeForCommenceField();
                    dc.AllowDBNull = true; // this is default, but setting it explicitly makes it more clear.
                }
            }
            // we would like to set relationships as well.
            // as it is, we don't know what our 'primary' table is at this point in the code
            // all we know it is the only table without a fkid field, but that's a little awkward to check.
            // we hack that by having a 'mock' primary table variable.
            List <DataRelation> relations = new List <DataRelation>();

            foreach (DataTable d in retval.Tables)
            {
                if (!d.Equals(primaryTable))
                {
                    DataRelation r = new DataRelation("rel_" + d.TableName,
                                                      primaryTable.TableName,
                                                      d.TableName,
                                                      new string[] { "id" },
                                                      new string[] { "fkid" },
                                                      true); // setting nested to true allows for nested XML exports
                    relations.Add(r);
                }
            }
            // add the relations to the dataset
            // tricky snag found on https://msdn.microsoft.com/en-us/library/2z22c2sz.aspx
            // "Any DataRelation object created by using this constructor must be added to the collection
            // with the AddRange method inside of a BeginInit and EndInit block.
            if (relations.Any())
            {
                retval.BeginInit();
                retval.Relations.AddRange(relations.ToArray());
                retval.EndInit();
            }
            return(retval);
        }