private void ProcessErrors(IList <EdmSchemaError> schemaErrors, Uri projectItemUri, EFArtifact artifact) { // since we will inevitably add *all* errors from the artifact set into the error list, we can easily // clear the entire error list here even though we just validate the CSDL. var errorList = ErrorListHelper.GetSingleDocErrorList(projectItemUri); if (errorList != null) { errorList.Clear(); } if (artifact == null) { Debug.Fail("Where is the artifact? We should have created it at least through the temporary model manager"); return; } // we have to remove both the RMV and SFG CSDL errors to prevent duplicates artifact.ArtifactSet.RemoveErrorsForArtifact(artifact, ErrorClass.Runtime_CSDL); // add all CSDL-based SFG errors to the artifact set if (schemaErrors.Count > 0) { foreach (var error in schemaErrors) { // construct an ErrorInfo with correct line/column number and add it to the artifact set. Note that the CodeGen EdmSchemaError line // refers to the line of the error inside the CSDL, so to get the line of the error in the edmx file we have to offset it by the line // number where the conceptual model begins. var edmxErrorLine = error.Line + artifact.ConceptualModel().GetLineNumber(); var efobject = artifact.FindEFObjectForLineAndColumn(edmxErrorLine, error.Column); var errorInfo = new ErrorInfo( GetErrorInfoSeverity(error), error.Message, efobject, error.ErrorCode, ErrorClass.Runtime_CSDL); artifact.ArtifactSet.AddError(errorInfo); } } // get all the ErrorInfos for this artifact and add it to the error list var artifactSet = artifact.ArtifactSet; Debug.Assert(artifactSet != null, "Where is the artifact set for this artifact?"); if (artifactSet != null) { var errors = artifactSet.GetArtifactOnlyErrors(artifact); if (errors.Count > 0) { // resolve the hierarchy and item id for adding to the error list var hierarchy = VSHelpers.GetVsHierarchy(ProjectItem.ContainingProject, Services.ServiceProvider); var itemId = VsUtils.GetProjectItemId(hierarchy, ProjectItem); Debug.Assert(hierarchy != null, "Why isn't there a hierarchy associated with this project item?"); Debug.Assert(itemId != VSConstants.VSITEMID_NIL, "There should be an item ID associated with this project item"); if (hierarchy != null && itemId != VSConstants.VSITEMID_NIL) { ErrorListHelper.AddErrorInfosToErrorList(errors, hierarchy, itemId); } } } }
// <summary> // This will do analysis to determine if a document should be opened // only in the XmlEditor. // </summary> internal override void DetermineIfArtifactIsDesignerSafe() { VsUtils.EnsureProvider(this); base.DetermineIfArtifactIsDesignerSafe(); // // TODO: we need to figure out how to deal with errors from the wizard. // when we clear the error list below, we lose errors that we put into the error // list when running the wizard. // // // Now update the VS error list with all of the errors we want to display, which are now in the EFArtifactSet. // var errorInfos = ArtifactSet.GetAllErrors(); if (errorInfos.Count > 0) { var currentProject = VSHelpers.GetProjectForDocument(Uri.LocalPath, PackageManager.Package); if (currentProject != null) { var hierarchy = VsUtils.GetVsHierarchy(currentProject, Services.ServiceProvider); if (hierarchy != null) { var fileFinder = new VSFileFinder(Uri.LocalPath); fileFinder.FindInProject(hierarchy); Debug.Assert(fileFinder.MatchingFiles.Count <= 1, "Unexpected count of matching files in project"); // if the EDMX file is not part of the project. if (fileFinder.MatchingFiles.Count == 0) { var docData = VSHelpers.GetDocData(PackageManager.Package, Uri.LocalPath) as IEntityDesignDocData; ErrorListHelper.AddErrorInfosToErrorList(errorInfos, docData.Hierarchy, docData.ItemId); } else { foreach (var vsFileInfo in fileFinder.MatchingFiles) { if (vsFileInfo.Hierarchy == VsUtils.GetVsHierarchy(currentProject, Services.ServiceProvider)) { var errorList = ErrorListHelper.GetSingleDocErrorList(vsFileInfo.Hierarchy, vsFileInfo.ItemId); if (errorList != null) { errorList.Clear(); ErrorListHelper.AddErrorInfosToErrorList(errorInfos, vsFileInfo.Hierarchy, vsFileInfo.ItemId); } else { Debug.Fail("errorList is null!"); } } } } } } } }
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); }
internal static bool UpdateEdmxAndEnvironment(ModelBuilderSettings settings) { var artifact = settings.Artifact as EntityDesignArtifact; if (artifact == null) { Debug.Fail("In trying to UpdateEdmxAndEnvironment(), No Artifact was found in the ModelBuilderSettings"); return(false); } // Update the app. or web.config, register build providers etc ConfigFileHelper.UpdateConfig(settings); if (settings.SsdlStringReader != null && settings.MslStringReader != null) { // Create the XmlReaders for the ssdl and msl text var ssdlXmlReader = XmlReader.Create(settings.SsdlStringReader); var mslXmlReader = XmlReader.Create(settings.MslStringReader); // Set up our post event to clear out the error list var cmd = new ReplaceSsdlAndMslCommand(ssdlXmlReader, mslXmlReader); cmd.PostInvokeEvent += (o, e) => { var errorList = ErrorListHelper.GetSingleDocErrorList(e.CommandProcessorContext.Artifact.Uri); if (errorList != null) { errorList.Clear(); } }; // Update the model (all inside 1 transaction so we don't get multiple undo's/redo's) var editingContext = PackageManager.Package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(settings.Artifact.Uri); var cpc = new CommandProcessorContext( editingContext, EfiTransactionOriginator.GenerateDatabaseScriptFromModelId, Resources.Tx_GenerateDatabaseScriptFromModel); var cp = new CommandProcessor(cpc, cmd); var addUseLegacyProviderCommand = ModelHelper.CreateSetDesignerPropertyValueCommandFromArtifact( cpc.Artifact, OptionsDesignerInfo.ElementName, OptionsDesignerInfo.AttributeUseLegacyProvider, settings.UseLegacyProvider.ToString()); if (addUseLegacyProviderCommand != null) { cp.EnqueueCommand(addUseLegacyProviderCommand); } // When the user had a v2 edmx file (it can happen when creating a new empty model in a project targeting // .NET Framework 4 and the project does not have refereces to any of EF dlls) and selected EF6 in // the "create database from model" wizard we need to update the artifact to use v3 schemas otherwise // there will be a watermark saying that the edmx is not correct for the EF version and needs to be updated. // We only want to run this command if the version really changed to avoid the overhead. if (artifact.SchemaVersion != settings.TargetSchemaVersion) { cp.EnqueueCommand(new RetargetXmlNamespaceCommand(artifact, settings.TargetSchemaVersion)); } cp.Invoke(); } // First let's get the canonical file path since DTE needs this if (!string.IsNullOrEmpty(settings.DdlFileName) && settings.DdlStringReader != null) { var canonicalFilePath = string.Empty; try { var fi = new FileInfo(settings.DdlFileName); canonicalFilePath = fi.FullName; } catch (Exception e) { Debug.Fail( "We should have caught this exception '" + e.Message + "' immediately after the user clicked the 'Finish' button"); VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, ModelWizard.Properties.Resources.ErrorCouldNotParseDdlFileName, settings.DdlFileName, e.Message)); return(false); } // Output the DDL file, catch any Exceptions, display them, and revert // back to the last page of the wizard. try { OutputDdl(canonicalFilePath, settings.DdlStringReader); } catch (Exception e) { if (e.InnerException == null) { VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, Resources.DatabaseCreation_ErrorWritingDdl, canonicalFilePath, e.Message)); } else { VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, Resources.DatabaseCreation_ErrorWritingDdlWithInner, canonicalFilePath, e.Message, e.InnerException.Message)); } return(false); } // Add DDL file to the project if it is inside the project string relativePath; if (VsUtils.TryGetRelativePathInProject(settings.Project, canonicalFilePath, out relativePath)) { AddDDLFileToProject(settings.Project, canonicalFilePath); } // Open the DDL file if it is not already open IVsUIHierarchy hier; uint itemId; IVsWindowFrame frame; if (VsShellUtilities.IsDocumentOpen( Services.ServiceProvider, canonicalFilePath, Guid.Empty, out hier, out itemId, out frame) == false) { VsShellUtilities.OpenDocument(Services.ServiceProvider, canonicalFilePath); } } return(true); }