private void DropObjects (SchemaRegistry registry, List<string> dropObjects, List<SchemaObject> addObjects) { // drop objects foreach (string objectName in dropObjects) { if (DroppingObject != null) DroppingObject (this, new SchemaEventArgs (SchemaEventType.BeforeDrop, objectName)); // drop any table dependencies, if any SchemaObjectType type = registry.GetObjectType (objectName); switch (type) { case SchemaObjectType.UserDefinedType: DropTypeDependencies(objectName, addObjects); break; case SchemaObjectType.View: DropViewDependencies (objectName, addObjects); break; case SchemaObjectType.Table: DropTableDepencencies(objectName, null, TableScriptOptions.IncludeTableModifiers | TableScriptOptions.AllXmlIndexes, true); break; case SchemaObjectType.PrimaryKey: DropTableDepencencies(SchemaObject.TableNameFromIndexName(objectName), addObjects, TableScriptOptions.AddAtEnd | TableScriptOptions.AllXmlIndexes, false); break; case SchemaObjectType.PrimaryXmlIndex: DropTableDepencencies(SchemaObject.TableNameFromIndexName(objectName), addObjects, TableScriptOptions.AddAtEnd | TableScriptOptions.SecondaryXmlIndexes, false); break; } SchemaObject.Drop (this, _connection, type, objectName); registry.DeleteObject (objectName); ResetScripter (); } }
/// <summary> /// Uninstall a schema group from the database. /// </summary> /// <remarks>This is a transactional operation</remarks> /// <param name="schemaGroup">The group to uninstall</param> /// <exception cref="ArgumentNullException">If schemaGroup is null</exception> /// <exception cref="SqlException">If any object fails to uninstall</exception> public void Uninstall (string schemaGroup) { // validate the arguments if (schemaGroup == null) throw new ArgumentNullException ("schemaGroup"); // the schema changes must be done in a transaction try { using (TransactionScope transaction = new TransactionScope ()) { // open the connection OpenConnection (); // make sure we have a schema registry SchemaRegistry registry = new SchemaRegistry (_connection); // sort the objects in drop order (reverse create order) List<string> names = registry.GetObjectNames (schemaGroup); names.Sort (delegate (string n1, string n2) { return -registry.GetObjectType (n1).CompareTo (registry.GetObjectType (n2)); }); // delete any objects that are in the specified schema group foreach (string objectName in names) { if (DroppingObject != null) DroppingObject (this, new SchemaEventArgs (SchemaEventType.BeforeDrop, objectName)); SchemaObjectType type = registry.GetObjectType (objectName); if (type == SchemaObjectType.Table) DropTableDepencencies(objectName, null, TableScriptOptions.IncludeTableModifiers, true); SchemaObject.Drop (this, _connection, type, objectName); registry.DeleteObject (objectName); } // commit the changes registry.Update (); transaction.Complete(); } } finally { _connection.Dispose (); } }
public string Install (string schemaGroup, SchemaObjectCollection objects, RebuildMode rebuildMode) { _scripts = new StringBuilder (); // validate the arguments if (schemaGroup == null) throw new ArgumentNullException ("schemaGroup"); if (objects == null) throw new ArgumentNullException ("objects"); // get the list of objects List<SchemaObject> schemaObjects = new List<SchemaObject> (objects); ValidateSchemaObjects (schemaObjects); for (int i = 0; i < objects.Count; i++) objects[i].OriginalOrder = i; // sort the list of objects in installation order schemaObjects.Sort (delegate (SchemaObject o1, SchemaObject o2) { int compare = o1.SchemaObjectType.CompareTo (o2.SchemaObjectType); if (compare == 0) compare = o1.OriginalOrder.CompareTo (o2.OriginalOrder); if (compare == 0) compare = String.Compare(o1.Name, o2.Name, StringComparison.OrdinalIgnoreCase); return compare; }); // the schema changes must be done in a transaction // since we don't pool the connection, we need to end the transaction before closing the connection try { using (TransactionScope transaction = new TransactionScope (TransactionScopeOption.Required, new TimeSpan (1, 0, 0, 0, 0))) { // open the connection OpenConnection (); // make sure we have a schema registry SchemaRegistry registry = new SchemaRegistry (_connection); // keep a list of all of the operations we need to perform List<string> dropObjects = new List<string> (); List<SchemaObject> addObjects = new List<SchemaObject> (); List<SchemaObject> tableUpdates = new List<SchemaObject> (); // look through all of the existing objects in the registry // create a delete instruction for all of the ones that should no longer be there foreach (string objectName in registry.GetObjectNames (schemaGroup)) { SchemaObject schemaObject = schemaObjects.Find (delegate (SchemaObject o) { return (o.Name.ToUpperInvariant() == objectName.ToUpperInvariant()); }); if (schemaObject == null) dropObjects.Add (objectName); } // sort to drop in reverse dependency order dropObjects.Sort (delegate (string o1, string o2) { int compare = -registry.GetObjectType (o1).CompareTo (registry.GetObjectType (o2)); if (compare == 0) compare = -registry.GetOriginalOrder(o1).CompareTo(registry.GetOriginalOrder(o2)); if (compare == 0) compare = -String.Compare(o1, o2, StringComparison.OrdinalIgnoreCase); return compare; }); // find out if we need to add anything foreach (SchemaObject schemaObject in schemaObjects) { // add any objects that aren't in the registry yet if (!registry.Contains (schemaObject.Name)) addObjects.Add (schemaObject); } // see if there are any drops or modifications bool hasChanges = dropObjects.Count != 0; if (!hasChanges) { foreach (SchemaObject schemaObject in schemaObjects) { if (registry.Contains (schemaObject.Name) && registry.GetSignature (schemaObject.Name) != schemaObject.Signature) { hasChanges = true; break; } } } // if there are changes, drop all of the easy items // drop and re-add all of the easy items if (hasChanges || (rebuildMode > RebuildMode.DetectChanges)) { for (int i = schemaObjects.Count - 1; i >= 0; i--) { SchemaObject schemaObject = schemaObjects [i]; if (registry.Contains (schemaObject.Name) && ( IsEasyToModify (schemaObject.SchemaObjectType) || (rebuildMode >= RebuildMode.RebuildSafe && CanRebuildSafely (schemaObject.SchemaObjectType)) || (rebuildMode >= RebuildMode.RebuildFull && CanRebuild (schemaObject.SchemaObjectType)) ) && !dropObjects.Contains (schemaObject.Name)) { dropObjects.Add (schemaObject.Name); addObjects.Add (schemaObject); } } } // drop and re-add everything else, using the scripting engine for (int i = schemaObjects.Count - 1; i >= 0; i--) { SchemaObject schemaObject = schemaObjects [i]; if (registry.Contains (schemaObject.Name) && registry.GetSignature (schemaObject.Name) != schemaObject.Signature && !IsEasyToModify (schemaObject.SchemaObjectType) && !dropObjects.Contains (schemaObject.Name)) ScheduleUpdate (dropObjects, addObjects, tableUpdates, schemaObject, true); } // sort to add in dependency order addObjects.Sort (delegate (SchemaObject o1, SchemaObject o2) { int compare = o1.SchemaObjectType.CompareTo (o2.SchemaObjectType); if (compare == 0) compare = o1.OriginalOrder.CompareTo (o2.OriginalOrder); if (compare == 0) compare = String.Compare (o1.Name, o2.Name, StringComparison.OrdinalIgnoreCase); return compare; }); // do the work DropObjects (registry, dropObjects, addObjects); UpdateTables (schemaGroup, registry, addObjects, tableUpdates); CreateObjects (schemaGroup, registry, addObjects); VerifyObjects (schemaObjects); // update the sigs on all of the records foreach (SchemaObject o in schemaObjects) registry.UpdateObject(o, schemaGroup); // commit the changes registry.Update (); transaction.Complete(); } } finally { _connection.Dispose (); } return _scripts.ToString (); }