protected override void PostInvoke(CommandProcessorContext cpc) { base.PostInvoke(cpc); if (_settings.HasExtensionChangedModel) { // // we validate here in the command so that we can throw to abort the transaction on errors // // // since the xml editor transaction hasn't been committed, the model state isn't totally valid and we get // a bunch of assertions if we use the model backed by the xml editor. For example, if we try to validate, // we get assertions about being unable to find line numbers. Because of this, we create a temporary artifact // on the updated model and validate that. // EntityDesignModelManager tempModelManager = null; EFArtifact tempArtifact = null; InMemoryXmlModelProvider modelProvider = null; try { var uri = _artifact.Uri; modelProvider = new InMemoryXmlModelProvider(uri, _artifact.XDocument.ToString()); // 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.. // We passed in instance of EFArtifactFactory to the model manager because we don't want the DiagramArtifact is instantiated and loaded because: // - We are only interested in Model validation; there is no need to load diagram. // - InMemoryXmlModelProvider will throw when we request to load diagram model since diagram model URI is different from entity model URI. tempModelManager = new EntityDesignModelManager(new EFArtifactFactory(), new VSArtifactSetFactory()); tempArtifact = tempModelManager.GetNewOrExistingArtifact(uri, modelProvider); ValidateArtifact(tempModelManager, tempArtifact, WizardKind.UpdateModel); } finally { if (tempArtifact != null) { tempArtifact.Dispose(); } if (tempModelManager != null) { tempModelManager.Dispose(); } if (modelProvider != null) { modelProvider.Dispose(); } } } }
public int OnAfterRenameFiles( int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgszMkOldNames, string[] rgszMkNewNames, VSRENAMEFILEFLAGS[] rgFlags) { var hr = VSConstants.S_OK; var handler = AfterRenameFile; if (handler != null) { for (var fileCount = 0; fileCount < cFiles; fileCount++) { var args = new ModelChangeEventArgs(); args.OldFileName = rgszMkOldNames[fileCount]; args.NewFileName = rgszMkNewNames[fileCount]; args.ProjectObj = GetProjectFromArray(cProjects, fileCount, rgpProjects, rgFirstIndices); if (args.ProjectObj == null) { continue; } var newUri = Utils.FileName2Uri(args.NewFileName); ModelManager modelManager = PackageManager.Package.ModelManager; var artifact = modelManager.GetArtifact(newUri); ModelManager tempModelManager = null; try { if (artifact == null && Path.GetExtension(args.NewFileName) .Equals(EntityDesignArtifact.EXTENSION_EDMX, StringComparison.CurrentCulture)) { tempModelManager = new EntityDesignModelManager(new EFArtifactFactory(), new VSArtifactSetFactory()); artifact = tempModelManager.GetNewOrExistingArtifact( newUri, new StandaloneXmlModelProvider(PackageManager.Package)); } args.Artifact = artifact; hr = handler(this, args); } finally { if (tempModelManager != null) { tempModelManager.Dispose(); } } } } return(hr); }
// <summary> // Loads document in an temporary model manager to see if it is designer safe. // </summary> private static bool IsUnloadedDocumentDesignerSafe(Uri uri) { Debug.Assert(uri != null, "uri is null"); using (var tempModelManager = new EntityDesignModelManager(new EFArtifactFactory(), new VSArtifactSetFactory())) { using (var xmlModelProvider = new StandaloneXmlModelProvider(PackageManager.Package)) { var artifact = tempModelManager.GetNewOrExistingArtifact(uri, xmlModelProvider); Debug.Assert(artifact != null, "failed to get the artifact to determine if it is designer-safe"); if (artifact == null) { return(true); } artifact.DetermineIfArtifactIsDesignerSafe(); return(artifact.IsDesignerSafe); } } }
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); }
protected override byte[] GenerateCode(string inputFileName, string inputFileContent, string defaultNamespace) { byte[] generatedBytes = null; var generatedCode = string.Empty; var projectItem = SiteServiceProvider.GetService(typeof(ProjectItem)) as ProjectItem; // Check if this is a rename operation here. The SFG gets called during a rename on website projects // and attempts to rollback the code-behind file if the SFG fails, but before the rename of the // code-behind file. We don't want to hose the existing code-behind file so we return back the bytes // of the previous code-behind file. if (projectItem != null && IsAfterARename(projectItem)) { var generatedCodeFile = GetCodeGenFilePathFromInputFile(inputFileName); if (File.Exists(generatedCodeFile)) { return(GetBytesOfExistingCodeGenFile(generatedCodeFile)); } } // init Language var languageOption = LanguageOption.GenerateCSharpCode; try { var defaultExtension = DefaultExtensionString.ToUpperInvariant(); if (defaultExtension.Contains(".CS")) { languageOption = LanguageOption.GenerateCSharpCode; } else if (defaultExtension.Contains(".VB")) { languageOption = LanguageOption.GenerateVBCode; } else { throw new NotSupportedException(Strings.UnknownLanguage); } } catch (Exception e) { string commentString; if (languageOption == LanguageOption.GenerateVBCode) { commentString = "' " + e.Message; } else { commentString = "// " + e.Message; } generatedBytes = Encoding.UTF8.GetBytes(commentString); return(generatedBytes); } // ensure that our package is loaded try { PackageManager.LoadEDMPackage(SiteServiceProvider); } catch (Exception) { // It would be nice to add an error in the error list, but you need an IServiceProvider to do this // We use our package usually for this, but here, our pacakge failed to load. Raise a message box VsUtils.ShowErrorDialog(Resources.LoadOurPackageError); string commentString; if (languageOption == LanguageOption.GenerateVBCode) { commentString = "' " + Resources.LoadOurPackageError; } else { commentString = "// " + Resources.LoadOurPackageError; } generatedBytes = Encoding.UTF8.GetBytes(commentString); return(generatedBytes); } if (InputFileHasContent(inputFileContent)) { var projectItemUri = Utils.FileName2Uri(inputFileName); ModelManager modelManager = PackageManager.Package.ModelManager; ModelManager tempModelManager = null; try { // First check the ModelManager to see if the artifact was loaded by the designer or if it was persisted from an earlier code-gen attempt var artifact = modelManager.GetArtifact(projectItemUri); if (artifact == null) { tempModelManager = new EntityDesignModelManager(new EFArtifactFactory(), new VSArtifactSetFactory()); artifact = tempModelManager.GetNewOrExistingArtifact( projectItemUri, new StandaloneXmlModelProvider(PackageManager.Package)); Debug.Assert(artifact != null, "We should have created the artifact from the temporary model manager"); // Since we created the artifact purely for code-gen, we need to mark it as such so the designer knows not to re-use this // artifact later. foreach (var codeGenArtifact in artifact.ArtifactSet.Artifacts) { codeGenArtifact.IsCodeGenArtifact = true; } } // First check if the 'CodeGenerationStrategy' option is set to 'Default'. // If there's no or empty value, we assume 'Default'. var codeGenStrategy = ModelHelper.GetDesignerPropertyValueFromArtifact( OptionsDesignerInfo.ElementName, OptionsDesignerInfo.AttributeCodeGenerationStrategy, artifact); if (String.IsNullOrEmpty(codeGenStrategy) || codeGenStrategy.Equals(Resources.Default)) { // navigate to the conceptual element var cModel = artifact.ConceptualModel(); if (cModel != null) { IList <EdmSchemaError> generatorErrors; using (var output = new StringWriter(CultureInfo.InvariantCulture)) { // set up namespace to use for code-gen. defaultNamespace is computed by VS to account for // folder path in the project, custom tool namespace, and differences between C#, VB, and web-site projects. defaultNamespace = GetCodeNamespace(defaultNamespace, artifact); // generate code generatorErrors = new LegacyCodeGenerationDriver(languageOption, artifact.SchemaVersion) .GenerateCode(artifact, defaultNamespace, output); generatedCode = output.ToString(); } // TODO: pass on validation to our designer so that we validate the MSL and SSDL in addition to the CSDL // Insert new errors into the ErrorList window ProcessErrors(generatorErrors, projectItemUri, artifact); if (generatorErrors.Count > 0 || string.IsNullOrEmpty(generatedCode)) { // We do not want to bring the error list to the front if there are code generation errors // since this could interrupt the editing of the model. // in case of errors generate a comment in the code which will indicate // that the file failed to generate properly generatedCode = GetCodeGenerationErrorComment(languageOption, inputFileName); } generatedBytes = Utils.StringToBytes(generatedCode, Encoding.UTF8); } } else { generatedCode = GetCodeGenerationDisabledComment(languageOption, inputFileName); generatedBytes = Utils.StringToBytes(generatedCode, Encoding.UTF8); } } catch (Exception e) { GeneratorErrorCallback(false, 0, e.Message, 0, 0); ErrorList.BringToFront(); } finally { if (tempModelManager != null) { tempModelManager.Dispose(); tempModelManager = null; } } } return(generatedBytes); }