Пример #1
0
        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);
                    }
                }
            }
        }
Пример #2
0
        // <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!");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #3
0
        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);
        }