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); }
private void ExecuteUndoRedoTest(string testName, string modelName, Action<CommandProcessorContext, EFArtifact> runTest) { var solnFilePath = Path.Combine(TestContext.DeploymentDirectory, @"TestData\InProc\UndoRedo\UndoRedo.sln"); var modelFilePath = Path.Combine(TestContext.DeploymentDirectory, @"TestData\InProc\UndoRedo\UndoRedo", modelName); var artifactUri = TestUtils.FileName2Uri(modelFilePath); var envDTE = VsIdeTestHostContext.Dte; Assert.IsNotNull(envDTE); envDTE.OpenSolution(solnFilePath); envDTE.OpenFile(artifactUri.LocalPath); var artifactHelper = new EFArtifactHelper(EFArtifactHelper.GetEntityDesignModelManager(VsIdeTestHostContext.ServiceProvider)); var entityDesignArtifact = (EntityDesignArtifact)artifactHelper.GetNewOrExistingArtifact(artifactUri); try { var editingContext = _package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(entityDesignArtifact.Uri); // Add DiagramId information in transactioncontext, so the correct diagram item will be created when Escher model is mutated. var transactionContext = new EfiTransactionContext(); transactionContext.Add( EfiTransactionOriginator.TransactionOriginatorDiagramId, new DiagramContextItem(entityDesignArtifact.DesignerInfo.Diagrams.FirstDiagram.Id.Value)); runTest( new CommandProcessorContext(editingContext, testName, testName + "Txn", entityDesignArtifact, transactionContext), entityDesignArtifact); } finally { envDTE.CloseDocument(modelFilePath, false); if (entityDesignArtifact != null) { entityDesignArtifact.Dispose(); } envDTE.CloseSolution(false); } }
private void ExecuteMigrateDiagramNodesTest(string projectName, Action <EntityDesignArtifact, CommandProcessorContext> runTest) { var modelPath = Path.Combine(TestContext.DeploymentDirectory, @"TestData\Model\v3\PubSimple.edmx"); UITestRunner.Execute( () => { EntityDesignArtifact entityDesignArtifact = null; Project project = null; try { project = Dte.CreateProject( TestContext.TestRunDirectory, projectName, DteExtensions.ProjectKind.Executable, DteExtensions.ProjectLanguage.CSharp); var projectItem = Dte.AddExistingItem(modelPath, project); Dte.OpenFile(projectItem.FileNames[0]); entityDesignArtifact = (EntityDesignArtifact) new EFArtifactHelper(EFArtifactHelper.GetEntityDesignModelManager(ServiceProvider)) .GetNewOrExistingArtifact(TestUtils.FileName2Uri(projectItem.FileNames[0])); Debug.Assert(entityDesignArtifact != null); var editingContext = _package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(entityDesignArtifact.Uri); // Create TransactionContext to indicate that the transactions are done from first diagram. // This is not used by MigrateDiagramInformationCommand but other commands in the callback methods. var transactionContext = new EfiTransactionContext(); transactionContext.Add( EfiTransactionOriginator.TransactionOriginatorDiagramId, new DiagramContextItem(entityDesignArtifact.DesignerInfo.Diagrams.FirstDiagram.Id.Value)); var commandProcessorContext = new CommandProcessorContext( editingContext, "MigrateDiagramNodesTest", projectName + "Txn", entityDesignArtifact, transactionContext); MigrateDiagramInformationCommand.DoMigrate(commandProcessorContext, entityDesignArtifact); Debug.Assert(entityDesignArtifact.DiagramArtifact != null); Debug.Assert( entityDesignArtifact.IsDesignerSafe, "Artifact should not be in safe mode after MigrateDiagramInformationCommand is executed."); Debug.Assert( new Uri(entityDesignArtifact.Uri.LocalPath + EntityDesignArtifact.EXTENSION_DIAGRAM) == entityDesignArtifact.DiagramArtifact.Uri); runTest(entityDesignArtifact, commandProcessorContext); } finally { if (entityDesignArtifact != null) { entityDesignArtifact.Dispose(); } if (project != null) { Dte.CloseSolution(false); } } }); }
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; }
private void ExecuteMigrateDiagramNodesTest(string projectName, Action<EntityDesignArtifact, CommandProcessorContext> runTest) { var modelPath = Path.Combine(TestContext.DeploymentDirectory, @"TestData\Model\v3\PubSimple.edmx"); UITestRunner.Execute(TestContext.TestName, () => { EntityDesignArtifact entityDesignArtifact = null; Project project = null; try { project = Dte.CreateProject( TestContext.TestRunDirectory, projectName, DteExtensions.ProjectKind.Executable, DteExtensions.ProjectLanguage.CSharp); var projectItem = Dte.AddExistingItem(modelPath, project); Dte.OpenFile(projectItem.FileNames[0]); entityDesignArtifact = (EntityDesignArtifact)new EFArtifactHelper(EFArtifactHelper.GetEntityDesignModelManager(ServiceProvider)) .GetNewOrExistingArtifact(TestUtils.FileName2Uri(projectItem.FileNames[0])); Debug.Assert(entityDesignArtifact != null); var editingContext = _package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(entityDesignArtifact.Uri); // Create TransactionContext to indicate that the transactions are done from first diagram. // This is not used by MigrateDiagramInformationCommand but other commands in the callback methods. var transactionContext = new EfiTransactionContext(); transactionContext.Add( EfiTransactionOriginator.TransactionOriginatorDiagramId, new DiagramContextItem(entityDesignArtifact.DesignerInfo.Diagrams.FirstDiagram.Id.Value)); var commandProcessorContext = new CommandProcessorContext( editingContext, "MigrateDiagramNodesTest", projectName + "Txn", entityDesignArtifact, transactionContext); MigrateDiagramInformationCommand.DoMigrate(commandProcessorContext, entityDesignArtifact); Debug.Assert(entityDesignArtifact.DiagramArtifact != null); Debug.Assert( entityDesignArtifact.IsDesignerSafe, "Artifact should not be in safe mode after MigrateDiagramInformationCommand is executed."); Debug.Assert( new Uri(entityDesignArtifact.Uri.LocalPath + EntityDesignArtifact.ExtensionDiagram) == entityDesignArtifact.DiagramArtifact.Uri); runTest(entityDesignArtifact, commandProcessorContext); } finally { if (entityDesignArtifact != null) { entityDesignArtifact.Dispose(); } if (project != null) { Dte.CloseSolution(false); } } }); }
private void ProcessViewModelChanges(string name, IList<ViewModelChange> viewModelChanges) { if (viewModelChanges != null && viewModelChanges.Count > 0) { var context = new EfiTransactionContext(); var containsDiagramChanges = viewModelChanges.Any(vmc => vmc.IsDiagramChange); context.Add( EfiTransactionOriginator.TransactionOriginatorDiagramId, new ModelDesigner.DiagramContextItem(DiagramId, containsDiagramChanges)); var cpc = new CommandProcessorContext( EditingContext, EfiTransactionOriginator.EntityDesignerOriginatorId, name, null, context); var cp = new CommandProcessor(cpc); // check if the DeleteUnmappedStorageEntitySetsProperty property is set if (Store.PropertyBag.ContainsKey(DeleteUnmappedStorageEntitySetsProperty)) { // if the property is set then unset it and add a // command to remove these for each item in the master list var unmappedMasterList = Store.PropertyBag[DeleteUnmappedStorageEntitySetsProperty] as List<ICollection<StorageEntitySet>>; Store.PropertyBag.Remove(DeleteUnmappedStorageEntitySetsProperty); if (unmappedMasterList != null) { foreach (var unmappedEntitySets in unmappedMasterList) { var duse = new DeleteUnmappedStorageEntitySetsCommand(unmappedEntitySets); cp.EnqueueCommand(duse); } } } var setParentUndoUnit = false; try { if (cpc.EditingContext.ParentUndoUnitStarted == false) { cpc.EditingContext.ParentUndoUnitStarted = true; cpc.Artifact.XmlModelProvider.BeginUndoScope(name); setParentUndoUnit = true; } var cmd = new DelegateCommand( () => { foreach (var change in viewModelChanges) { change.Invoke(cpc); } }); cp.EnqueueCommand(cmd); cp.Invoke(); } catch (Exception e) { if (!(e is CommandValidationFailedException || e is FileNotEditableException)) { Debug.Fail("Exception thrown while committing change to Model. " + e.Message); } throw; } finally { if (setParentUndoUnit) { cpc.EditingContext.ParentUndoUnitStarted = false; cpc.Artifact.XmlModelProvider.EndUndoScope(); } } } }