public void GetModelGenErrors_on_EntityDesignArtifact_always_returns_null()
 {
     var modelManager = new Mock<ModelManager>(null, null).Object;
     var modelProvider = new Mock<XmlModelProvider>().Object;
     using (var artifact = new EntityDesignArtifact(modelManager, new Uri("urn:dummy"), modelProvider))
     {
         Assert.Null(artifact.GetModelGenErrors());
     }
 }
Exemple #2
0
        public void GetModelGenErrors_on_EntityDesignArtifact_always_returns_null()
        {
            var modelManager  = new Mock <ModelManager>(null, null).Object;
            var modelProvider = new Mock <XmlModelProvider>().Object;

            using (var artifact = new EntityDesignArtifact(modelManager, new Uri("urn:dummy"), modelProvider))
            {
                Assert.Null(artifact.GetModelGenErrors());
            }
        }
 public EnumTypeViewModel(EntityDesignArtifact artifact, string underlyingType)
 {
     Initialize();
     _underlyingType = String.IsNullOrWhiteSpace(underlyingType) ? ModelConstants.Int32PropertyType : underlyingType;
     _isFlag = false;
     _name = String.Empty;
     _artifact = artifact;
     _isValid = false;
     _externalTypeName = String.Empty;
     _isReferenceExternalType = false;
 }
        internal static void DoMigrate(CommandProcessorContext cpc, EntityDesignArtifact artifact)
        {
            var xmlModelProvider = artifact.XmlModelProvider as VSXmlModelProvider;
            Debug.Assert(xmlModelProvider != null, "Artifact's model provider is not type of VSXmlModelProvider.");
            if ((xmlModelProvider != null)
                && (xmlModelProvider.UndoManager != null))
            {
                var undoManager = xmlModelProvider.UndoManager;
                try
                {
                    // We need to temporarily disable the Undo Manager because this operation is not undoable.
                    if (undoManager != null)
                    {
                        undoManager.Enable(0);
                    }

                    var command = new MigrateDiagramInformationCommand(artifact);
                    var processor = new CommandProcessor(cpc, shouldNotifyObservers: false);
                    processor.EnqueueCommand(command);
                    processor.Invoke();

                    Debug.Assert(artifact.DiagramArtifact != null, "Diagram artifact should have been created by now.");
                    if (artifact.DiagramArtifact != null)
                    {
                        // Ensure that diagram file is added to the project.
                        var service = PackageManager.Package.GetService(typeof(DTE)) as DTE;
                        service.ItemOperations.AddExistingItem(artifact.DiagramArtifact.Uri.LocalPath);

                        // Reload the artifacts.
                        artifact.ReloadArtifact();
                        artifact.IsDirty = true;

                        // The code below ensures mapping window and model-browser window are refreshed.
                        Debug.Assert(
                            PackageManager.Package.DocumentFrameMgr != null, "Could not find the DocumentFrameMgr for this package");
                        if (PackageManager.Package.DocumentFrameMgr != null)
                        {
                            PackageManager.Package.DocumentFrameMgr.SetCurrentContext(cpc.EditingContext);
                        }
                    }
                }
                finally
                {
                    if (undoManager != null)
                    {
                        undoManager.Enable(1);
                    }
                }
            }
        }
        public EnumTypeViewModel(EnumType enumType)
        {
            Initialize();
            Debug.Assert(enumType != null, "Parameter enum type is null");
            if (enumType != null)
            {
                _enumType = enumType;
                _artifact = enumType.Artifact as EntityDesignArtifact;

                _isFlag = enumType.IsFlags.Value;
                _name = enumType.Name.Value;
                _underlyingType = enumType.UnderlyingType.Value;
                _externalTypeName = enumType.ExternalTypeName.Value;
                _isReferenceExternalType = (String.IsNullOrWhiteSpace(_externalTypeName) == false);

                foreach (var member in enumType.Members())
                {
                    var vm = new EnumTypeMemberViewModel(this, member);
                    vm.PropertyChanged += enumTypeMember_PropertyChanged;
                    Members.Add(vm);
                }
            }
            _isValid = true;
        }
        internal static void GenerateDatabaseScriptFromModel(EntityDesignArtifact artifact)
        {
            VsUtils.EnsureProvider(artifact);

            var project = VSHelpers.GetProjectForDocument(artifact.Uri.LocalPath, PackageManager.Package);
            var sp = Services.ServiceProvider;
            ModelBuilderWizardForm form;
            ModelBuilderWizardForm.WizardMode startMode;
            ModelBuilderSettings settings;

            // Start the hourglass, especially because we'll be incurring a perf hit from validating
            using (new VsUtils.HourglassHelper())
            {
                // Before running the Generate Database wizard, we have to make sure that the C-Side validates
                VisualStudioEdmxValidator.LoadAndValidateFiles(artifact.Uri);

                if (
                    artifact.ArtifactSet.GetAllErrors()
                        .Count(ei => ei.ErrorClass == ErrorClass.Runtime_CSDL || ei.ErrorClass == ErrorClass.Escher_CSDL) > 0)
                {
                    VsUtils.ShowErrorDialog(Resources.DatabaseCreation_ValidationFailed);
                    return;
                }

                // set up ModelBuilderSettings
                settings = SetupSettingsAndModeForDbPages(
                    sp, project, artifact, false,
                    ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndDBGenSummary,
                    ModelBuilderWizardForm.WizardMode.PerformDBGenSummaryOnly, out startMode);

                form = new ModelBuilderWizardForm(sp, settings, startMode);
            }

            var originalSchemaVersion = settings.TargetSchemaVersion;

            try
            {
                // start the ModelBuilderWizardForm; this will start the workflow in another thread.
                form.Start();
            }
            catch (Exception e)
            {
                VsUtils.ShowErrorDialog(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Resources.ModelObjectItemWizard_UnexpectedExceptionHasOccurred,
                        e.Message));
                return;
            }

            // if Wizard was cancelled or the user hit 'X' to close window
            // no need for any further action
            if (form.WizardCancelled
                || !form.WizardFinished)
            {
                return;
            }

            // If database was configured, add DbContext templates
            if (startMode == ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndDBGenSummary)
            {
                var edmxItem = VsUtils.GetProjectItemForDocument(artifact.Uri.LocalPath, sp);
                new DbContextCodeGenerator().AddDbContextTemplates(edmxItem, settings.UseLegacyProvider);

                // We need to reload the artifact if we updated the edmx as part of generating
                // model from the database.
                if (settings.TargetSchemaVersion != originalSchemaVersion)
                {
                    artifact.ReloadArtifact();
                }
            }
        }
        // <summary>
        //     Creates commands to remove function imports and complex types corresponding to results if ones exist.
        // </summary>
        // <param name="designArtifact">Artifact.</param>
        // <returns>IEnumerable of commands for deleting function imports and corresponding complex types.</returns>
        // <remarks>
        //     This function should be called only from RunFinished() method as we don't check whether complex types we
        //     are removing are not used by other function imports or entities.
        // </remarks>
        private static IEnumerable<Command> CreateRemoveFunctionImportCommands(EntityDesignArtifact designArtifact)
        {
            // we were instructed not to create FunctionImports - but runtime has created them automatically so actually need to delete any which have been created
            var model = designArtifact.ConceptualModel;
            var cec = (ConceptualEntityContainer)model.FirstEntityContainer;
            foreach (var fi in cec.FunctionImports())
            {
                yield return fi.GetDeleteCommand();

                if (fi.IsReturnTypeComplexType)
                {
                    var complexType = model.ComplexTypes().SingleOrDefault(
                        c => ReferenceEquals(c, fi.ReturnTypeAsComplexType.Target));

                    Debug.Assert(
                        complexType != null,
                        string.Format("Complex type {0} for FunctionImport {1} does not exist", complexType.Name, fi.Name));

                    if (complexType != null)
                    {
                        yield return complexType.GetDeleteCommand();
                    }
                }
            }
        }
        // internal static to make it more testable
        internal static CommandProcessor PrepareCommandsAndIntegrityChecks(
            ModelBuilderSettings modelBuilderSettings,
            EditingContext editingContext,
            EntityDesignArtifact designArtifact)
        {
            Debug.Assert(modelBuilderSettings != null, "modelBuilderSettings != null");
            Debug.Assert(editingContext != null, "editingContext != null");
            Debug.Assert(designArtifact != null, "artifact != null");

            var commands = new List<Command>();
            if (modelBuilderSettings.NewFunctionSchemaProcedures != null
                && modelBuilderSettings.NewFunctionSchemaProcedures.Count > 0)
            {
                // user selected to create new FunctionImports, but don't create the composable ones as these have already been created by the runtime
                ProgressDialogHelper.ProcessStoredProcedureReturnTypeInformation(
                    designArtifact,
                    modelBuilderSettings.NewFunctionSchemaProcedures,
                    commands,
                    shouldCreateComposableFunctionImports: false);
            }
            else
            {
                commands.AddRange(CreateRemoveFunctionImportCommands(designArtifact));
            }

            // for SqlServer and SqlServerCe we need to add integrity checks - see the comment below
            if (commands.Count > 0
                || designArtifact.IsSqlFamilyProvider())
            {
                // set up CommandProcessorContext
                var cpc = new CommandProcessorContext(
                    editingContext,
                    EfiTransactionOriginator.CreateNewModelId,
                    Resources.Tx_CreateFunctionImport);

                // We propagate facets by default only for Sql Server or Sql Server CE since for other providers facets in C-Space might be intentionally
                // out of sync with facets from S-Space and we should not break this. For Sql Server and Sql Server CE facets should be in sync in most cases.
                if (designArtifact.IsSqlFamilyProvider())
                {
                    // Add integrity check to enforce synchronizing C-side Property facets to S-side values
                    PropagateStoragePropertyFacetsToConceptualModel.AddRule(cpc, designArtifact);
                }

                return new CommandProcessor(cpc, commands);
            }

            // no commands or integrity checks to run
            return null;
        }
        //internal for testing
        internal static void ReversionModel(
            IEdmPackage package, EditingContext editingContext, EntityDesignArtifact entityDesignArtifact, Version targetSchemaVersion)
        {
            var cpc = new CommandProcessorContext(
                editingContext, EfiTransactionOriginator.EntityDesignerOriginatorId,
                EntityDesignerResources.RetargetDocumentFromWatermarkTransactionName, entityDesignArtifact);

            RetargetXmlNamespaceCommand.RetargetArtifactXmlNamespaces(cpc, entityDesignArtifact, targetSchemaVersion);

            // The code below ensure that our mapping window works property after the command is executed.
            Debug.Assert(package.DocumentFrameMgr != null, "Could not find the DocumentFrameMgr for this package");
            if (package.DocumentFrameMgr != null)
            {
                package.DocumentFrameMgr.SetCurrentContext(editingContext);
            }
        }
        internal void AddMissingAssociationConnectors(EntityDesignArtifact efArtifact, out bool addedMissingShapes)
        {
            addedMissingShapes = false;
            Debug.Assert(efArtifact != null, "EFArtifact is null");
            if (efArtifact != null)
            {
                // Now, for all associations, ensure that an association connector is created.
                var dslDiagram = Diagram as EntityDesignerDiagram;
                if (efArtifact.ConceptualModel() != null
                    && dslDiagram != null)
                {
                    var associationsMaterializedAsConnectors = new HashSet<ModelAssociation>();
                    foreach (
                        var connector in
                            efArtifact.DesignerInfo.Diagrams.Items.Where(d => d.Id.Value == DiagramId)
                                .SelectMany(d => d.AssociationConnectors))
                    {
                        // First check if there's a ModelElement for this.
                        var associationConnector = dslDiagram.ModelElement.ModelXRef.GetExisting(connector) as AssociationConnector;
                        if (associationConnector != null
                            && connector.Association.Target != null
                            && !associationsMaterializedAsConnectors.Contains(connector.Association.Target))
                        {
                            associationsMaterializedAsConnectors.Add(connector.Association.Target);
                        }
                    }

                    var cpc = new CommandProcessorContext(
                        efArtifact.EditingContext,
                        EfiTransactionOriginator.EntityDesignerOriginatorId,
                        "Restore Excluded Elements");
                    var cp = new CommandProcessor(cpc, shouldNotifyObservers: true);

                    foreach (var association in efArtifact.ConceptualModel().Associations())
                    {
                        if (!associationsMaterializedAsConnectors.Contains(association))
                        {
                            var shouldAddConnector = true;
                            var entityTypesOnEnds = association.AssociationEnds().Select(ae => ae.Type.Target);
                            foreach (var entityType in entityTypesOnEnds)
                            {
                                if (entityType != null
                                    && entityType.GetAntiDependenciesOfType<Model.Designer.EntityTypeShape>()
                                           .Any(ets => ets.Diagram.Id == DiagramId) == false)
                                {
                                    shouldAddConnector = false;
                                    break;
                                }
                            }

                            if (shouldAddConnector)
                            {
                                var modelDiagram = dslDiagram.ModelElement.ModelXRef.GetExisting(dslDiagram) as ModelDiagram;
                                if (modelDiagram != null)
                                {
                                    cp.EnqueueCommand(new CreateAssociationConnectorCommand(modelDiagram, association));
                                }
                            }
                        }
                    }

                    if (cp.CommandCount > 0)
                    {
                        cp.Invoke();
                        addedMissingShapes = true;
                    }
                }
            }
        }
        internal void AddMissingEntityTypeShapes(EntityDesignArtifact efArtifact, out bool addedMissingShapes)
        {
            addedMissingShapes = false;
            Debug.Assert(efArtifact != null, "EFArtifact is null");
            if (efArtifact != null)
            {
                // Now, for all entitytypes, ensure that an entitytype shape is created.
                var dslDiagram = Diagram as EntityDesignerDiagram;
                if (efArtifact.ConceptualModel() != null
                    && dslDiagram != null)
                {
                    var entityTypesMaterializedAsShapes = new HashSet<Model.Entity.EntityType>();
                    foreach (
                        var designerEntityTypeShape in
                            efArtifact.DesignerInfo.Diagrams.Items.Where(d => d.Id.Value == DiagramId).SelectMany(d => d.EntityTypeShapes))
                    {
                        // First check if there's a ModelElement for this.
                        var entityTypeShape = dslDiagram.ModelElement.ModelXRef.GetExisting(designerEntityTypeShape) as EntityTypeShape;
                        if (entityTypeShape != null
                            && designerEntityTypeShape.EntityType.Target != null
                            && !entityTypesMaterializedAsShapes.Contains(designerEntityTypeShape.EntityType.Target))
                        {
                            entityTypesMaterializedAsShapes.Add(designerEntityTypeShape.EntityType.Target);
                        }
                    }

                    var cpc = new CommandProcessorContext(
                        efArtifact.EditingContext,
                        EfiTransactionOriginator.EntityDesignerOriginatorId,
                        "Restore Excluded Elements");
                    var cp = new CommandProcessor(cpc, shouldNotifyObservers: true);

                    foreach (var entityType in efArtifact.ConceptualModel().EntityTypes())
                    {
                        if (!entityTypesMaterializedAsShapes.Contains(entityType))
                        {
                            var modelDiagram = dslDiagram.ModelElement.ModelXRef.GetExisting(dslDiagram) as ModelDiagram;
                            if (modelDiagram != null)
                            {
                                cp.EnqueueCommand(new CreateEntityTypeShapeCommand(modelDiagram, entityType));
                            }
                        }
                    }

                    if (cp.CommandCount > 0)
                    {
                        cp.Invoke();
                        addedMissingShapes = true;
                    }
                }
            }
        }
        internal static void UpdateModelFromDatabase(EntityDesignArtifact artifact)
        {
            VsUtils.EnsureProvider(artifact);

            var serviceProvider = Services.ServiceProvider;
            var project = VSHelpers.GetProjectForDocument(artifact.Uri.LocalPath, serviceProvider);

            // set up ModelBuilderSettings for startMode=PerformDatabaseConfigAndSelectTables
            ModelBuilderWizardForm.WizardMode startMode;
            var settings =
                SetupSettingsAndModeForDbPages(
                    serviceProvider, project, artifact, true,
                    ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndSelectTables,
                    ModelBuilderWizardForm.WizardMode.PerformSelectTablesOnly, out startMode);
            settings.WizardKind = WizardKind.UpdateModel;

            // use existing storage namespace as new storage namespace
            if (null != artifact.StorageModel()
                && null != artifact.StorageModel().Namespace
                && !string.IsNullOrEmpty(artifact.StorageModel().Namespace.Value))
            {
                settings.StorageNamespace = artifact.StorageModel().Namespace.Value;
            }

            // use existing model namespace as new model namespace (this only affects the temporary
            // artifact but there is a situation where the C-side EntityContainer has been given the
            // same name as the default model namespace where not setting this causes the temporary
            // artifact to be unreadable because of symbol clashes)
            if (null != artifact.ConceptualModel()
                && null != artifact.ConceptualModel().Namespace
                && !string.IsNullOrEmpty(artifact.ConceptualModel().Namespace.Value))
            {
                settings.ModelNamespace = artifact.ConceptualModel().Namespace.Value;
            }
            
            settings.ModelBuilderEngine = new UpdateModelFromDatabaseModelBuilderEngine();

            // call the ModelBuilderWizardForm
            var form = new ModelBuilderWizardForm(serviceProvider, settings, startMode);

            try
            {
                form.Start();
            }
            catch (Exception e)
            {
                VsUtils.ShowErrorDialog(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.ModelObjectItemWizard_UnexpectedExceptionHasOccurred,
                        e.Message));
                return;
            }

            // if Wizard was cancelled or the user hit 'X' to close window
            // no need for any further action
            if (form.WizardCancelled
                || !form.WizardFinished)
            {
                return;
            }

            // Update the app. or web.config, register build providers etc
            ConfigFileHelper.UpdateConfig(settings);

            // use form.ModelBuilderSettings to look at accumulated info and
            // take appropriate action
            var editingContext = PackageManager.Package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(artifact.Uri);
            var shouldReloadArtifact = ProcessAccumulatedInfo(editingContext, artifact, settings);

            // If database was configured, add DbContext templates
            if (startMode == ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndSelectTables)
            {
                var edmxItem = VsUtils.GetProjectItemForDocument(artifact.Uri.LocalPath, serviceProvider);
                new DbContextCodeGenerator().AddDbContextTemplates(edmxItem, settings.UseLegacyProvider);
            }

            // We can reload only after we added EF references to the project otherwise we would get a watermark
            // saying that the schema version does not match the referenced EF version which would not be true.
            // If we reload becuase there was an extension that potentially modified the artifact then it does not matter.
            if (shouldReloadArtifact)
            {
                artifact.ReloadArtifact();
                artifact.IsDirty = true;
            }
        }
        private static bool ProcessAccumulatedInfo(
            EditingContext editingContext, EntityDesignArtifact existingArtifact, ModelBuilderSettings settings)
        {
            var schemaVersionChanged = existingArtifact.SchemaVersion != settings.TargetSchemaVersion;

            EntityDesignModelManager tempModelManager = null;
            FileInfo tempEdmxFile = null;
            Uri tempEdmxFileUri = null;

            try
            {
                // set up new temporary ModelManager
                // NOTE:  use an EFArtifact with VSArtifactSet.  This is so we get the in-vs behavior of artifact sets, 
                // but don't rely on VS loading the model into the RDT, etc..
                tempModelManager = new EntityDesignModelManager(new EFArtifactFactory(), new VSArtifactSetFactory());

                tempEdmxFile = ConstructTempEdmxFile(settings);
                tempEdmxFileUri = new Uri(tempEdmxFile.FullName, UriKind.Absolute);
                var tempArtifactBasedOnDatabase = tempModelManager.GetNewOrExistingArtifact(tempEdmxFileUri, new VanillaXmlModelProvider());

                // if a model generation extension has changed the model, ensure that it is 
                // valid before we start to process it
                if (settings.HasExtensionChangedModel)
                {
                    ValidateArtifact(tempModelManager, tempArtifactBasedOnDatabase, WizardKind.Generate);
                }

                // Note: later we want the diagram shapes and connectors to be created in the current active diagram
                // so set TransactionContext appropriately.
                EfiTransactionContext transactionContext = null;
                var contextItem = editingContext.Items.GetValue<DiagramManagerContextItem>();
                if (contextItem != null
                    && contextItem.DiagramManager != null)
                {
                    var activeDiagram = contextItem.DiagramManager.ActiveDiagram;
                    if (activeDiagram != null)
                    {
                        transactionContext = new EfiTransactionContext();
                        transactionContext.Add(
                            EfiTransactionOriginator.TransactionOriginatorDiagramId, new DiagramContextItem(activeDiagram.DiagramId));
                    }
                }

                // clear search if active (Note: in Model.Tests it is OK for below to be null)
                var explorerInfo = editingContext.Items.GetValue<ExplorerWindow.ExplorerInfo>();
                if (explorerInfo != null)
                {
                    var explorerFrame = explorerInfo._explorerFrame;
                    if (explorerFrame != null)
                    {
                        if (explorerFrame.SearchIsActive)
                        {
                            explorerFrame.ResetSearchCommand.Execute(null);
                        }
                    }
                }

                var cpc = new CommandProcessorContext(
                    editingContext, EfiTransactionOriginator.UpdateModelFromDatabaseId,
                    Resources.Tx_UpdateModelFromDatabase, null, transactionContext);

                if (schemaVersionChanged)
                {
                    // changing namespaces must be done in a separate transaction otherwise XmlEditor
                    // will not pick-up changes made to xml after namespaces are changed 
                    CommandProcessor.InvokeSingleCommand(
                        cpc,
                        new RetargetXmlNamespaceCommand(existingArtifact, settings.TargetSchemaVersion));
                }

                // Update the existing artifact based on tempArtifactBasedOnDatabase
                var commands = new List<Command>();
                var cmd = new UpdateModelFromDatabaseCommand(tempArtifactBasedOnDatabase);
                commands.Add(cmd);

                // set up our post event to clear out the error list
                cmd.PostInvokeEvent +=
                    (o, e) =>
                        {
                            var errorList =
                                ErrorListHelper.GetSingleDocErrorList(e.CommandProcessorContext.Artifact.Uri);
                            if (errorList != null)
                            {
                                errorList.Clear();
                            }
                        };

                DesignerInfo designerInfo;
                if (existingArtifact.DesignerInfo().TryGetDesignerInfo(OptionsDesignerInfo.ElementName, out designerInfo))
                {
                    var optionsDesignerInfo = designerInfo as OptionsDesignerInfo;
                    Debug.Assert(optionsDesignerInfo != null, "expected non-null optionsDesignerInfo");
                    if (optionsDesignerInfo != null)
                    {
                        // pluralization checkbox
                        AddUpdateDesignerPropertyCommand(
                            optionsDesignerInfo.CheckPluralizationInWizard,
                            OptionsDesignerInfo.AttributeEnablePluralization,
                            settings.UsePluralizationService, optionsDesignerInfo, commands);

                        // include FKs in model checkbox
                        AddUpdateDesignerPropertyCommand(
                            optionsDesignerInfo.CheckIncludeForeignKeysInModel,
                            OptionsDesignerInfo.AttributeIncludeForeignKeysInModel,
                            settings.IncludeForeignKeysInModel, optionsDesignerInfo, commands);

                        // ensure UseLegacyProvider is set
                        AddUpdateDesignerPropertyCommand(
                            optionsDesignerInfo.UseLegacyProvider,
                            OptionsDesignerInfo.AttributeUseLegacyProvider,
                            settings.UseLegacyProvider, optionsDesignerInfo, commands);
                    }
                }

                // create a new FunctionImport for every new Function created (whether composable or not)
                // (or delete Functions if ProgressDialog did not finish successfully)
                // Note: this must take place as a DelegateCommand as ProcessStoredProcedureReturnTypeInformation()
                // can depend on finding the existing Functions to delete. And it won't find them until the
                // ReplaceSsdlCommand within UpdateModelFromDatabaseCommand has executed.
                var createMatchingFunctionImportsDelegateCommand = new DelegateCommand(
                    () =>
                        {
                            var functionImportCommands = new List<Command>();
                            ProgressDialogHelper.ProcessStoredProcedureReturnTypeInformation(
                                existingArtifact, settings.NewFunctionSchemaProcedures, functionImportCommands, true);

                            if (functionImportCommands.Count > 0)
                            {
                                new CommandProcessor(cpc, functionImportCommands)
                                    .Invoke();
                            }
                        });
                commands.Add(createMatchingFunctionImportsDelegateCommand);

                // if needed, create a command to dispatch any extensions
                if (EscherExtensionPointManager.LoadModelGenerationExtensions().Length > 0)
                {
                    var dispatchCommand = new DispatchToExtensionsCommand(settings);
                    commands.Add(dispatchCommand);
                }

                // do all the work here in one transaction
                new CommandProcessor(cpc, commands)
                    .Invoke();

                // if an extension has changed the model, do a full reload
                if (schemaVersionChanged || settings.HasExtensionChangedModel)
                {
                    return true;
                }
                else
                {
                    // reset the is-designer safe flag - this can be set incorrectly when the document is reloaded after ssdl has been updated,
                    // but csdl & msl haven't.  Here, the model is correct, but we need to get views to refresh themselves after we
                    // reset the is-designer-safe flag.
                    // Perf note: reloading the artifact can take some time - so only reload if IsDesignerSafe has changed
                    var isDesignerSafeBefore = existingArtifact.IsDesignerSafe;
                    existingArtifact.DetermineIfArtifactIsDesignerSafe();
                    var isDesignerSafeAfter = existingArtifact.IsDesignerSafe;
                    if (isDesignerSafeAfter != isDesignerSafeBefore)
                    {
                        existingArtifact.FireArtifactReloadedEvent();
                    }
                }
            }
            finally
            {
                // remove tempArtifactBasedOnDatabase to dispose EFObject's properly
                if (tempEdmxFileUri != null
                    && tempModelManager != null)
                {
                    tempModelManager.ClearArtifact(tempEdmxFileUri);
                }

                // dispose of our temp model manager
                if (tempModelManager != null)
                {
                    tempModelManager.Dispose();
                }

                // delete temporary file
                if (tempEdmxFile != null
                    && tempEdmxFile.Exists)
                {
                    try
                    {
                        tempEdmxFile.Delete();
                    }
                    catch (IOException)
                    {
                        // do nothing if delete fails
                    }
                }
            }

            return false;
        }
 // Intentionally set this to private because we only want this command to be instantiated from static method and not to be combined with other command.
 private MigrateDiagramInformationCommand(EntityDesignArtifact artifact)
 {
     _artifact = artifact;
 }