Beispiel #1
0
 public DBSchema GetSchema()
 {
     using (var scope = this.BeginScope()) {
         var schema =
             new DBSchema {
             DatabaseID = this.ConnectionString,
             Tables     = NormalizeTables(GetDenormalizedTableDescriptions()),
             Triggers   = NormalizeTriggers(GetDenormalizedTriggerDescriptions()),
             SQL        = string.Empty
         };
         if (ArtificialKeys != null)
         {
             ArtificialKeys.ApplyToSchema(schema);
         }
         schema.FinishedBuilding();
         return(schema);
     }
 }
Beispiel #2
0
        internal void ApplyToSchema(DBSchema schema)
        {
            if (Tables == null)
            {
                throw new SoftwareException("Artificial keys did not specify in tables");
            }

            foreach (var table in Tables)
            {
                if (!schema.ContainsTable(table.Name))
                {
                    throw new SoftwareException("Artificial Keys cannot be applied as table '{0}' does not exist", table.Name);
                }

                var tableSchema = schema[table.Name];


                if (table.PrimaryKey != null)
                {
                    // Remove primary key if present (auto override)
                    tableSchema.PrimaryKey = null;

                    if (tableSchema.PrimaryKey != null)
                    {
                        throw new SoftwareException("Artificial primary key '{0}' cannot be applied to table '{1}' as it already contains a primary key", table.PrimaryKey.Name, tableSchema.Name);
                    }

                    if (!table.PrimaryKey.Columns.Any(c => tableSchema.ContainsColumn(c.Name)))
                    {
                        throw new SoftwareException("Artificial primary key '{0}' cannot be applied to table '{1}' as the specified columns '{2}' do not exist", table.PrimaryKey.Name, tableSchema.Name, table.PrimaryKey.Columns.First(c => !tableSchema.ContainsColumn(c.Name)).Name);
                    }

                    if (!string.IsNullOrEmpty(table.PrimaryKey.Sequence) && table.PrimaryKey.Columns.Count() != 1)
                    {
                        throw new SoftwareException("Artificial primary key '{0}' cannot be applied to table '{1}' as a sequence can only apply to a single primary key column", table.PrimaryKey.Name, tableSchema.Name);
                    }

                    if (table.PrimaryKey.AutoIncrement && table.PrimaryKey.Columns.Count() != 1)
                    {
                        throw new SoftwareException("Artificial primary key '{0}' cannot be applied to table '{1}' as autoincrement can only apply to a single primary key column", table.PrimaryKey.Name, tableSchema.Name);
                    }

                    if ((!string.IsNullOrEmpty(table.PrimaryKey.Sequence) || table.PrimaryKey.AutoIncrement) && !tableSchema.GetColumn(table.PrimaryKey.Columns[0].Name).Type.IsIntegerNumeric())
                    {
                        throw new SoftwareException("Artificial primary key '{0}' with sequence and/or autoincrement cannot be applied to table '{1}' as it's primary key is not an integer-based type", table.PrimaryKey.Name, tableSchema.Name);
                    }

                    tableSchema.PrimaryKey = new DBPrimaryKeySchema {
                        Name        = table.PrimaryKey.Name,
                        Sequence    = table.PrimaryKey.Sequence,
                        ColumnNames = (from c in table.PrimaryKey.Columns select c.Name).ToArray(),
                        KeyType     = DBKeyType.Artificial | (table.PrimaryKey.AutoIncrement ? DBKeyType.AutoCalculated : !string.IsNullOrEmpty(table.PrimaryKey.Sequence) ? DBKeyType.Sequenced : DBKeyType.None),
                        SQL         = XmlProvider.WriteToString(this)
                    };

                    tableSchema.PrimaryKeyColumns = (from pk in tableSchema.PrimaryKey.ColumnNames select tableSchema.GetColumn(pk)).ToArray();

                    tableSchema.PrimaryKeyColumns.ForEach(pkCol => pkCol.IsPrimaryKey = true);
                    if (table.PrimaryKey.AutoIncrement)
                    {
                        tableSchema.PrimaryKeyColumns[0].IsAutoIncrement = true;
                    }

                    if (!string.IsNullOrEmpty(table.PrimaryKey.Sequence))
                    {
                        tableSchema.PrimaryKeyColumns[0].Sequence = table.PrimaryKey.Sequence;
                    }
                }

                if (table.UniqueConstraints != null && table.UniqueConstraints.Length > 0)
                {
                    var schemaUniqueKeys = tableSchema.UniqueConstraints.ToDictionary(z => z.Name);
                    var newUniqueKeys    = new List <DBUniqueConstraintSchema>();
                    foreach (var uniqueKey in table.UniqueConstraints)
                    {
                        if (schemaUniqueKeys.ContainsKey(uniqueKey.Name))
                        {
                            throw new SoftwareException("Artificial unique constraint '{0}' cannot be applied to table '{1}' as a unique constraint with that name already exists", uniqueKey.Name, tableSchema.Name);
                        }

                        if (!uniqueKey.Columns.Any(c => tableSchema.ContainsColumn(c.Name)))
                        {
                            throw new SoftwareException("Artificial unique constraint '{0}' cannot be applied to table '{1}' as it references non-existent column(s)", uniqueKey.Name, tableSchema.Name);
                        }

                        var ucCols = tableSchema.Columns.Where(c => c.Name.IsIn(uniqueKey.Columns.Select(x => x.Name))).ToArray();
                        ucCols.ForEach(ucCol => ucCol.IsUnique = true);
                        newUniqueKeys.Add(
                            new DBUniqueConstraintSchema {
                            Name    = uniqueKey.Name,
                            Columns = ucCols.Select(c => c.Name).ToArray(),
                            KeyType = DBKeyType.Artificial,
                            SQL     = XmlProvider.WriteToString(uniqueKey)
                        }
                            );
                    }
                    tableSchema.UniqueConstraints = tableSchema.UniqueConstraints.Concat(newUniqueKeys).ToArray();
                }
            }

            // Foreign keys are processed after all primary/unique keys (for complex dependency graphs)
            foreach (var table in Tables)
            {
                var tableSchema = schema[table.Name];
                if (table.ForeignKeys != null && table.ForeignKeys.Length > 0)
                {
                    var schemaForeignKeys = tableSchema.ForeignKeys.ToDictionary(z => z.Name);
                    var newForeignKeys    = new List <DBForeignKeySchema>();
                    foreach (var foreignKey in table.ForeignKeys)
                    {
                        if (schemaForeignKeys.ContainsKey(foreignKey.Name))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as it already contains a foreign key by that name", foreignKey.Name, tableSchema.Name);
                        }

                        if (!foreignKey.Columns.Any(c => tableSchema.ContainsColumn(c.Name)))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as it references a non-existent column '{2}'", foreignKey.Name, tableSchema.Name, foreignKey.Columns.First(c => !tableSchema.ContainsColumn(c.Name)).Name);
                        }

                        if (string.IsNullOrEmpty(foreignKey.ReferenceTable))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as it did not specify a reference table", foreignKey.Name, tableSchema.Name);
                        }

                        if (!schema.ContainsTable(foreignKey.ReferenceTable))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as it referenced a non-existant reference table '{2}'", foreignKey.Name, tableSchema.Name, foreignKey.ReferenceTable);
                        }

                        var primaryKeyTable = schema[foreignKey.ReferenceTable];
                        if (!foreignKey.Columns.Any(c => primaryKeyTable.ContainsColumn(c.Name)))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as it links to a non-existant column '{2}'", foreignKey.Name, tableSchema.Name, foreignKey.Columns.First(c => !primaryKeyTable.ContainsColumn(c.Name)).Name);
                        }

                        var referenceColumnsInPK = primaryKeyTable.PrimaryKey != null && primaryKeyTable.PrimaryKey.ColumnNames.ContainSameElements(foreignKey.Columns.Select(c => c.Name));
                        var referenceColumnsInUC = primaryKeyTable.UniqueConstraints.Any(uc => uc.Columns.ContainSameElements(foreignKey.Columns.Select(c => c.Name)));

                        if (!referenceColumnsInPK && !referenceColumnsInUC)
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as the specified reference columns are not primary or unique keys in table '{2}'", foreignKey.Name, tableSchema.Name, foreignKey.ReferenceTable);
                        }

                        if (foreignKey.Columns.Any(c => string.IsNullOrEmpty(c.References)))
                        {
                            throw new SoftwareException("Artificial foreign key '{0}' cannot be applied to table '{1}' as some column(s) did not link to a primary key table column", foreignKey.Name, tableSchema.Name);
                        }

                        var fcCols = tableSchema.Columns.Where(c => c.Name.IsIn(foreignKey.Columns.Select(x => x.Name))).ToArray();
                        fcCols.ForEach(ucCol => ucCol.IsForeignKey = true);
                        newForeignKeys.Add(
                            new DBForeignKeySchema {
                            Name              = foreignKey.Name,
                            ForeignKeyTable   = tableSchema.Name,
                            ForeignKeyColumns = (from c in foreignKey.Columns select c.Name).ToArray(),
                            ReferenceTable    = foreignKey.ReferenceTable,
                            ReferenceColumns  = (from c in foreignKey.Columns select c.References).ToArray(),
                            KeyType           = DBKeyType.Artificial,
                            SQL = XmlProvider.WriteToString(foreignKey)
                        }
                            );
                    }
                    tableSchema.ForeignKeys = newForeignKeys.Concat(tableSchema.ForeignKeys).ToArray();
                }
            }
        }
 public static IEnumerable <string> ConvertToStorableFormat(this DBSchema schema, IEnumerable <object> values)
 {
     return(values.Select(v => Convert.ChangeType(v, typeof(string)) as string));
 }