public void CanCreateAndOpenConnection_passes_the_latest_EF_version_as_the_max_version()
        {
            var mockEntityConnection  = new Mock <EntityConnection>();
            var mockConnectionFactory = new Mock <StoreSchemaConnectionFactory>();

            Version version;

            mockConnectionFactory
            .Setup(
                f => f.Create(
                    It.IsAny <IDbDependencyResolver>(), It.IsAny <string>(), It.IsAny <string>(),
                    It.IsAny <Version>(), out version))
            .Returns(mockEntityConnection.Object);

            ModelBuilderEngine.CanCreateAndOpenConnection(
                mockConnectionFactory.Object, "fakeInvariantName", "fakeInvariantName", "fakeConnectionString");

            mockConnectionFactory.Verify(
                f => f.Create(
                    It.IsAny <IDbDependencyResolver>(),
                    It.Is <string>(s => s == "fakeInvariantName"),
                    It.Is <string>(s => s == "fakeConnectionString"),
                    It.Is <Version>(v => v == EntityFrameworkVersion.Latest),
                    out version),
                Times.Once());
        }
        public void CanCreateAndOpenConnection_returns_true_for_valid_connection()
        {
            var mockEntityConnection  = new Mock <EntityConnection>();
            var mockConnectionFactory = new Mock <StoreSchemaConnectionFactory>();

            Version version;

            mockConnectionFactory
            .Setup(
                f => f.Create(
                    It.IsAny <IDbDependencyResolver>(), It.IsAny <string>(), It.IsAny <string>(),
                    It.IsAny <Version>(), out version))
            .Returns(mockEntityConnection.Object);

            Assert.True(
                ModelBuilderEngine.CanCreateAndOpenConnection(
                    mockConnectionFactory.Object, "fakeInvariantName", "fakeInvariantName", "fakeConnectionString"));
        }
        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
                ModelBuilderEngine.SetupSettingsAndModeForDbPages(
                    sp, project, artifact, false,
                    ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndDBGenSummary,
                    ModelBuilderWizardForm.WizardMode.PerformDBGenSummaryOnly, out startMode, out settings);

                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();
                }
            }
        }
        internal static void UpdateModelFromDatabase(EntityDesignArtifact artifact)
        {
            VsUtils.EnsureProvider(artifact);

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

            // set up ModelBuilderSettings for startMode=PerformDatabaseConfigAndSelectTables
            ModelBuilderWizardForm.WizardMode startMode;
            ModelBuilderSettings settings;

            ModelBuilderEngine.SetupSettingsAndModeForDbPages(
                serviceProvider, project, artifact, true,
                ModelBuilderWizardForm.WizardMode.PerformDatabaseConfigAndSelectTables,
                ModelBuilderWizardForm.WizardMode.PerformSelectTablesOnly, out startMode, out settings);
            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
            ConfigFileUtils.UpdateConfig(settings);

            // clear all previous errors for this document first
            ErrorListHelper.ClearErrorsForDocAcrossLists(settings.Artifact.Uri);

            // log any errors that occurred during model-gen to the error list
            ErrorListHelper.LogUpdateModelWizardErrors(settings.ModelBuilderEngine.Errors, settings.Artifact.Uri.LocalPath);

            // 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;
            }
        }
        internal 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>();
                    ModelBuilderEngine.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);
        }