/// <summary>
        /// Deserializes any custom database objects defined in the specified <see cref="XElement"/> object into the specified <see cref="HyperDbSchema"/> object.
        /// </summary>
        /// <param name="parent">The <see cref="XElement"/> object containing the XML definitions for the stored procedures.</param>
        /// <param name="dbSchema">The <see cref="HyperDbSchema"/> object to receive the deserialized tables.</param>
        private void DeserializeCustomDbObjects(XElement parent, HyperDbSchema dbSchema)
        {
            var customDbConfigType   = Type.GetType(GetRequiredAttribute(parent, "type"), true); // Deliberately throw an exception if we can't load the type
            var customDbConfigObject = CreateInstanceAs <IDbCustomConfiguration>(customDbConfigType);

            customDbConfigObject.Deserialize(parent, _scriptWriterTypes);

            dbSchema.DbCustomConfig = customDbConfigObject;
        }
        /// <summary>
        /// Deserializes any tables defined in the specified <see cref="XElement"/> object into the specified <see cref="HyperDbSchema"/> object.
        /// </summary>
        /// <param name="parent">The <see cref="XElement"/> object containing the XML definitions for the tables.</param>
        /// <param name="dbSchema">The <see cref="HyperDbSchema"/> object to receive the deserialized tables.</param>
        private void DeserializeTables(XElement parent, HyperDbSchema dbSchema)
        {
            var defaultScriptWriterName = GetOptionalAttribute(parent, "scriptWriter", null);

            foreach (var tableElement in parent.Elements(_hyperDbXmlNamespace + "table"))
            {
                var table = new HyperDbTable
                {
                    Name = GetRequiredAttribute(tableElement, "name")
                };

                var     versionString = GetOptionalAttribute(tableElement, "version", null);
                Version versionObject;
                if (Version.TryParse(versionString, out versionObject))
                {
                    table.Version = versionObject;
                }

                var scriptWriterType = _defaultDbTableScriptWriterType;
                var scriptWriterName = GetOptionalAttribute(tableElement, "scriptWriter", defaultScriptWriterName);
                if (!string.IsNullOrWhiteSpace(scriptWriterName))
                {
                    if (_scriptWriterTypes.ContainsKey(scriptWriterName))
                    {
                        scriptWriterType = _scriptWriterTypes[scriptWriterName];
                    }
                    else
                    {
                        throw new HyperDbSchemaConfigurationException("Invalid " + typeof(IDbTableScriptWriter).Name + " was specified for table " + table.Name + ".");
                    }
                }

                var columnCollectionElement = tableElement.Element(_hyperDbXmlNamespace + "columns");
                if (columnCollectionElement != null)
                {
                    DeserializeColumns(columnCollectionElement, table);
                }

                var constraintCollectionElement = tableElement.Element(_hyperDbXmlNamespace + "constraints");
                if (constraintCollectionElement != null)
                {
                    DeserializeConstraints(constraintCollectionElement, table);
                }

                // Finally fill in our custom writer objects
                var scriptWriterObject = CreateInstanceAs <IDbTableScriptWriter>(scriptWriterType);
                scriptWriterObject.Source = table;
                table.ScriptWriter        = scriptWriterObject;

                dbSchema.Tables.Add(table);
            }
        }
        /// <summary>
        /// Deserializes any database schemas defined in the specified <see cref="XContainer"/>.
        /// </summary>
        /// <param name="parent">The <see cref="XContainer"/> containing the XML definitions for the database schemas.</param>
        private void DeserializeDatabaseSchemas(XContainer parent)
        {
            foreach (var schemaElement in parent.Elements(_hyperDbXmlNamespace + "databaseSchema"))
            {
                var dbSchema = new HyperDbSchema
                {
                    Name = GetRequiredAttribute(schemaElement, "name")
                };

                var     versionString = GetOptionalAttribute(schemaElement, "version", null);
                Version versionObject;
                if (Version.TryParse(versionString, out versionObject))
                {
                    dbSchema.Version = versionObject;
                }

                var tableCollectionElement           = schemaElement.Element(_hyperDbXmlNamespace + "tables");
                var storedProcedureCollectionElement = schemaElement.Element(_hyperDbXmlNamespace + "storedProcedures");
                var customDbObjectParent             = schemaElement.Element(_hyperDbXmlNamespace + "customDbObjects");
                var scriptCollectionElement          = schemaElement.Element(_hyperDbXmlNamespace + "scripts");

                if (tableCollectionElement != null)
                {
                    DeserializeTables(tableCollectionElement, dbSchema);
                }

                if (storedProcedureCollectionElement != null)
                {
                    DeserializeStoredProcedures(storedProcedureCollectionElement, dbSchema);
                }

                if (customDbObjectParent != null)
                {
                    DeserializeCustomDbObjects(customDbObjectParent, dbSchema);
                }

                if (scriptCollectionElement != null)
                {
                    DeserializeScripts(scriptCollectionElement, dbSchema);
                }

                _dbSchemas.TryAdd(dbSchema.Name, dbSchema);
            }
        }
 /// <summary>
 /// Deserializes any scripts defined in the specified <see cref="XContainer"/> object into the specified <see cref="HyperDbSchema"/> object.
 /// </summary>
 /// <param name="parent">The <see cref="XContainer"/> object containing the XML definitions for the scripts.</param>
 /// <param name="dbSchema">The <see cref="HyperDbSchema"/> object to receive the deserialized tables.</param>
 private void DeserializeScripts(XContainer parent, HyperDbSchema dbSchema)
 {
     // TODO: Phase 2 item
 }
 /// <summary>
 /// Deserializes any stored procedures defined in the specified <see cref="XContainer"/> object into the specified <see cref="HyperDbSchema"/> object.
 /// </summary>
 /// <param name="parent">The <see cref="XContainer"/> object containing the XML definitions for the stored procedures.</param>
 /// <param name="dbSchema">The <see cref="HyperDbSchema"/> object to receive the deserialized tables.</param>
 private void DeserializeStoredProcedures(XContainer parent, HyperDbSchema dbSchema)
 {
     // TODO: Phase 2 item
 }