Exemplo n.º 1
0
        private async Task <bool> ChooseDataBaseConnectionByUiHintAsync(ReverseEngineerOptions options)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var databaseList = vsDataHelper.GetDataConnections(package);

            if (databaseList != null && databaseList.Any())
            {
                var dataBaseInfo = databaseList.Values.FirstOrDefault(m => m.ConnectionName == options.UiHint);
                if (dataBaseInfo != null)
                {
                    options.ConnectionString = dataBaseInfo.ConnectionString;
                    options.DatabaseType     = dataBaseInfo.DatabaseType;
                    return(true);
                }
            }

            var dacpacList = await EnvDteExtensions.GetDacpacFilesInActiveSolutionAsync();

            if (dacpacList != null && dacpacList.Any() && !string.IsNullOrEmpty(options.UiHint) &&
                options.UiHint.EndsWith(".sqlproj", StringComparison.OrdinalIgnoreCase))
            {
                var candidate = dacpacList
                                .Where(m => !string.IsNullOrWhiteSpace(m) && m.EndsWith(".sqlproj"))
                                .FirstOrDefault(m => m.Equals(options.UiHint, StringComparison.OrdinalIgnoreCase));

                if (candidate != null)
                {
                    options.Dacpac = candidate;
                    return(true);
                }
            }

            return(false);
        }
        private void VerifySQLServerRightsAndVersion(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (options.DatabaseType == DatabaseType.SQLServer && string.IsNullOrEmpty(options.Dacpac))
            {
                if (options.ConnectionString.ToLowerInvariant().Contains(".database.windows.net") &&
                    options.ConnectionString.ToLowerInvariant().Contains("active directory interactive"))
                {
                    return;
                }

                var rightsAndVersion = reverseEngineerHelper.HasSqlServerViewDefinitionRightsAndVersion(options.ConnectionString);

                if (rightsAndVersion.Item1 == false)
                {
                    VSHelper.ShowMessage(ReverseEngineerLocale.SqlServerNoViewDefinitionRights);
                }

                if (rightsAndVersion.Item2.Major < 11)
                {
                    VSHelper.ShowMessage(string.Format(ReverseEngineerLocale.SQLServerVersionNotSupported, rightsAndVersion.Item2));
                }
            }
        }
        private void SaveOptions(Project project, string optionsPath, ReverseEngineerOptions options, Tuple <List <Schema>, string> renamingOptions)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (File.Exists(optionsPath) && File.GetAttributes(optionsPath).HasFlag(FileAttributes.ReadOnly))
            {
                EnvDteHelper.ShowError($"Unable to save options, the file is readonly: {optionsPath}");
                return;
            }

            if (!File.Exists(optionsPath + ".ignore"))
            {
                File.WriteAllText(optionsPath, options.Write(), Encoding.UTF8);
                project.ProjectItems.AddFromFile(optionsPath);
            }

            if (renamingOptions.Item1 != null && !File.Exists(renamingOptions.Item2 + ".ignore") && renamingOptions.Item1.Count() > 0)
            {
                if (File.Exists(renamingOptions.Item2) && File.GetAttributes(renamingOptions.Item2).HasFlag(FileAttributes.ReadOnly))
                {
                    EnvDteHelper.ShowError($"Unable to save renaming options, the file is readonly: {renamingOptions.Item2}");
                    return;
                }

                File.WriteAllText(renamingOptions.Item2, CustomNameOptionsExtensions.Write(renamingOptions.Item1), Encoding.UTF8);
                project.ProjectItems.AddFromFile(renamingOptions.Item2);
            }
        }
        private async Task <bool> LoadDataBaseObjectsAsync(ReverseEngineerOptions options, DatabaseInfo dbInfo, Tuple <List <Schema>, string> namingOptionsAndPath)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            _package.Dte2.StatusBar.Animate(true, _icon);
            var predefinedTables = !string.IsNullOrEmpty(options.Dacpac)
                                       ? await GetDacpacTablesAsync(options.Dacpac, options.CodeGenerationMode == CodeGenerationMode.EFCore5)
                                       : await GetTablesAsync(dbInfo, options.CodeGenerationMode == CodeGenerationMode.EFCore5, options.Schemas?.ToArray());

            _package.Dte2.StatusBar.Animate(false, _icon);

            var preselectedTables = new List <SerializationTableModel>();

            if (options.Tables?.Count > 0)
            {
                var normalizedTables = reverseEngineerHelper.NormalizeTables(options.Tables, dbInfo.DatabaseType == DatabaseType.SQLServer);
                preselectedTables.AddRange(normalizedTables);
            }

            _package.Dte2.StatusBar.Clear();

            var ptd = _package.GetView <IPickTablesDialog>()
                      .AddTables(predefinedTables, namingOptionsAndPath.Item1)
                      .PreselectTables(preselectedTables);

            var pickTablesResult = ptd.ShowAndAwaitUserResponse(true);

            options.Tables          = pickTablesResult.Payload.Objects.ToList();
            options.CustomReplacers = pickTablesResult.Payload.CustomReplacers.ToList();
            return(pickTablesResult.ClosedByOK);
        }
Exemplo n.º 5
0
        private DatabaseConnectionModel GetDatabaseInfo(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var dbInfo = new DatabaseConnectionModel();

            if (!string.IsNullOrEmpty(options.ConnectionString))
            {
                dbInfo.ConnectionString = options.ConnectionString;
                dbInfo.DatabaseType     = options.DatabaseType;
            }

            if (!string.IsNullOrEmpty(options.Dacpac))
            {
                dbInfo.DatabaseType      = DatabaseType.SQLServerDacpac;
                dbInfo.ConnectionString  = $"Data Source=(local);Initial Catalog={Path.GetFileNameWithoutExtension(options.Dacpac)};Integrated Security=true;";
                options.ConnectionString = dbInfo.ConnectionString;
                options.DatabaseType     = dbInfo.DatabaseType;

                options.Dacpac = _package.Dte2.DTE.BuildSqlProj(options.Dacpac);
                if (string.IsNullOrEmpty(options.Dacpac))
                {
                    EnvDteHelper.ShowMessage(ReverseEngineerLocale.UnableToBuildSelectedDatabaseProject);
                    return(null);
                }
            }

            if (dbInfo.DatabaseType == DatabaseType.Undefined)
            {
                EnvDteHelper.ShowError($"{ReverseEngineerLocale.UnsupportedProvider}");
                return(null);
            }

            return(dbInfo);
        }
        private async Task <bool> ChooseDataBaseConnectionAsync(ReverseEngineerOptions options)
        {
            var databaseList = vsDataHelper.GetDataConnections(_package);
            var dacpacList   = await EnvDTEExtensions.GetDacpacFilesInActiveSolutionAsync();

            var psd = _package.GetView <IPickServerDatabaseDialog>();

            if (databaseList != null && databaseList.Any())
            {
                psd.PublishConnections(databaseList.Select(m => new DatabaseConnectionModel
                {
                    ConnectionName   = m.Value.ConnectionName,
                    ConnectionString = m.Value.ConnectionString,
                    DatabaseType     = m.Value.DatabaseType,
                    DataConnection   = m.Value.DataConnection,
                }));
            }

            if (dacpacList != null && dacpacList.Any())
            {
                psd.PublishDefinitions(dacpacList.Select(m => new DatabaseDefinitionModel
                {
                    FilePath = m
                }));
            }

            if (options.FilterSchemas && options.Schemas != null && options.Schemas.Any())
            {
                psd.PublishSchemas(options.Schemas);
            }

            psd.PublishCodeGenerationMode(options.CodeGenerationMode);

            if (!string.IsNullOrEmpty(options.UiHint))
            {
                psd.PublishUiHint(options.UiHint);
            }

            var pickDataSourceResult = psd.ShowAndAwaitUserResponse(true);

            if (!pickDataSourceResult.ClosedByOK)
            {
                return(false);
            }

            options.CodeGenerationMode = pickDataSourceResult.Payload.CodeGenerationMode;
            options.FilterSchemas      = pickDataSourceResult.Payload.FilterSchemas;
            options.Schemas            = options.FilterSchemas ? pickDataSourceResult.Payload.Schemas?.ToList() : null;
            options.UiHint             = pickDataSourceResult.Payload.UiHint;
            options.Dacpac             = pickDataSourceResult.Payload.Definition?.FilePath;

            if (pickDataSourceResult.Payload.Connection != null)
            {
                options.ConnectionString = pickDataSourceResult.Payload.Connection.ConnectionString;
                options.DatabaseType     = pickDataSourceResult.Payload.Connection.DatabaseType;
            }

            return(true);
        }
Exemplo n.º 7
0
        public static async Task <ReverseEngineerResult> LaunchExternalRunnerAsync(ReverseEngineerOptions options, CodeGenerationMode codeGenerationMode, Project project)
        {
            var databaseObjects = options.Tables;

            if (!databaseObjects.Any(t => t.ObjectType == ObjectType.Table))
            {
                // No tables selected, so add a dummy table in order to generate an empty DbContext
                databaseObjects.Add(new SerializationTableModel($"Dummy_{new Guid(GuidList.guidDbContextPackagePkgString)}", ObjectType.Table, null));
            }

            var commandOptions = new ReverseEngineerCommandOptions
            {
                ConnectionString                   = options.ConnectionString,
                ContextClassName                   = options.ContextClassName,
                CustomReplacers                    = options.CustomReplacers,
                Dacpac                             = options.Dacpac,
                DatabaseType                       = options.DatabaseType,
                DefaultDacpacSchema                = options.DefaultDacpacSchema,
                IncludeConnectionString            = options.IncludeConnectionString,
                OutputPath                         = options.OutputPath,
                ContextNamespace                   = options.ContextNamespace,
                ModelNamespace                     = options.ModelNamespace,
                OutputContextPath                  = options.OutputContextPath,
                UseSchemaFolders                   = options.UseSchemaFolders,
                ProjectPath                        = options.ProjectPath,
                ProjectRootNamespace               = options.ProjectRootNamespace,
                SelectedHandlebarsLanguage         = options.SelectedHandlebarsLanguage,
                SelectedToBeGenerated              = options.SelectedToBeGenerated,
                Tables                             = databaseObjects,
                UseDatabaseNames                   = options.UseDatabaseNames,
                UseFluentApiOnly                   = options.UseFluentApiOnly,
                UseHandleBars                      = options.UseHandleBars,
                UseInflector                       = options.UseInflector,
                UseLegacyPluralizer                = options.UseLegacyPluralizer,
                UseSpatial                         = options.UseSpatial,
                UseHierarchyId                     = options.UseHierarchyId,
                UseDbContextSplitting              = options.UseDbContextSplitting,
                UseNodaTime                        = options.UseNodaTime,
                UseBoolPropertiesWithoutDefaultSql = options.UseBoolPropertiesWithoutDefaultSql,
                UseNullableReferences              = options.UseNullableReferences,
                UseNoConstructor                   = options.UseNoConstructor,
                UseNoNavigations                   = options.UseNoNavigations,
                UseNoObjectFilter                  = options.UseNoObjectFilter,
                UseNoDefaultConstructor            = options.UseNoDefaultConstructor,
                UseManyToManyEntity                = options.UseManyToManyEntity,
                RunCleanup                         = AdvancedOptions.Instance.RunCleanup,
                UseMultipleSprocResultSets         = AdvancedOptions.Instance.DiscoverMultipleResultSets,
                OptionsPath                        = options.OptionsPath,
                LegacyLangVersion                  = await project.IsLegacyAsync(),
                MergeDacpacs                       = AdvancedOptions.Instance.MergeDacpacs,
                UseLegacyResultSetDiscovery        = AdvancedOptions.Instance.UseLegacyResultSetDiscovery,
                UseAsyncCalls                      = AdvancedOptions.Instance.PreferAsyncCalls,
            };

            var launcher = new EfRevEngLauncher(commandOptions, codeGenerationMode);

            return(await launcher.GetOutputAsync());
        }
        private async Task <bool> SetNullableAsync(ReverseEngineerOptions options, Project project)
        {
            var nullable = await project.GetAttributeAsync("Nullable");

            if (string.Equals(nullable, "enable", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(nullable, "annotations", StringComparison.OrdinalIgnoreCase))
            {
                return(true);
            }

            return(await project.IsNetFrameworkAsync() ? false : options.UseNullableReferences);
        }
Exemplo n.º 9
0
        public static async Task <ReverseEngineerResult> LaunchExternalRunnerAsync(ReverseEngineerOptions options, CodeGenerationMode codeGenerationMode)
        {
            var databaseObjects = options.Tables;

            if (databaseObjects.Where(t => t.ObjectType == ObjectType.Table).Count() == 0)
            {
                // No tables selected, so add a dummy table in order to generate an empty DbContext
                databaseObjects.Add(new SerializationTableModel($"Dummy_{new Guid(GuidList.guidDbContextPackagePkgString)}", ObjectType.Table, null));
            }

            var commandOptions = new ReverseEngineerCommandOptions
            {
                ConnectionString                   = options.ConnectionString,
                ContextClassName                   = options.ContextClassName,
                CustomReplacers                    = options.CustomReplacers,
                Dacpac                             = options.Dacpac,
                DatabaseType                       = options.DatabaseType,
                DefaultDacpacSchema                = options.DefaultDacpacSchema,
                IncludeConnectionString            = options.IncludeConnectionString,
                OutputPath                         = options.OutputPath,
                ContextNamespace                   = options.ContextNamespace,
                ModelNamespace                     = options.ModelNamespace,
                OutputContextPath                  = options.OutputContextPath,
                UseSchemaFolders                   = options.UseSchemaFolders,
                ProjectPath                        = options.ProjectPath,
                ProjectRootNamespace               = options.ProjectRootNamespace,
                SelectedHandlebarsLanguage         = options.SelectedHandlebarsLanguage,
                SelectedToBeGenerated              = options.SelectedToBeGenerated,
                Tables                             = databaseObjects,
                UseDatabaseNames                   = options.UseDatabaseNames,
                UseFluentApiOnly                   = options.UseFluentApiOnly,
                UseHandleBars                      = options.UseHandleBars,
                UseInflector                       = options.UseInflector,
                UseLegacyPluralizer                = options.UseLegacyPluralizer,
                UseSpatial                         = options.UseSpatial,
                UseDbContextSplitting              = options.UseDbContextSplitting,
                UseNodaTime                        = options.UseNodaTime,
                UseBoolPropertiesWithoutDefaultSql = options.UseBoolPropertiesWithoutDefaultSql,
                UseNullableReferences              = options.UseNullableReferences,
                UseNoConstructor                   = options.UseNoConstructor,
                UseNoNavigations                   = options.UseNoNavigations,
                UseNoObjectFilter                  = options.UseNoObjectFilter,
                UseNoDefaultConstructor            = options.UseNoDefaultConstructor,
            };

            var launcher = new EfRevEngLauncher(commandOptions, codeGenerationMode);

            return(await launcher.GetOutputAsync());
        }
        private void SaveOptions(Project project, string optionsPath, ReverseEngineerOptions options, Tuple <List <Schema>, string> renamingOptions)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (!File.Exists(optionsPath + ".ignore"))
            {
                File.WriteAllText(optionsPath, options.Write(), Encoding.UTF8);
                project.ProjectItems.AddFromFile(optionsPath);
            }

            if (renamingOptions.Item1 != null && !File.Exists(renamingOptions.Item2 + ".ignore") && renamingOptions.Item1.Count() > 0)
            {
                File.WriteAllText(renamingOptions.Item2, CustomNameOptionsExtensions.Write(renamingOptions.Item1), Encoding.UTF8);
                project.ProjectItems.AddFromFile(renamingOptions.Item2);
            }
        }
        private bool ChooseDataBaseConnectionByUiHint(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var databaseList = vsDataHelper.GetDataConnections(_package);

            if (databaseList != null && databaseList.Any())
            {
                var dataBaseInfo = databaseList.Values.FirstOrDefault(m => m.Caption == options.UiHint);
                if (dataBaseInfo != null)
                {
                    options.ConnectionString = dataBaseInfo.ConnectionString;
                    options.DatabaseType     = dataBaseInfo.DatabaseType;
                    return(true);
                }
            }
            return(false);
        }
        private void VerifySQLServerRightsAndVersion(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (options.DatabaseType == DatabaseType.SQLServer && string.IsNullOrEmpty(options.Dacpac))
            {
                var rightsAndVersion = reverseEngineerHelper.HasSqlServerViewDefinitionRightsAndVersion(options.ConnectionString);

                if (rightsAndVersion.Item1 == false)
                {
                    EnvDteHelper.ShowMessage("The SQL Server user does not have 'VIEW DEFINITION' rights, default constraints may not be available.");
                }

                if (rightsAndVersion.Item2.Major < 11)
                {
                    EnvDteHelper.ShowMessage($"SQL Server version {rightsAndVersion.Item2} may not be supported.");
                }
            }
        }
        private void VerifySQLServerRightsAndVersion(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (options.DatabaseType == DatabaseType.SQLServer && string.IsNullOrEmpty(options.Dacpac))
            {
                var rightsAndVersion = reverseEngineerHelper.HasSqlServerViewDefinitionRightsAndVersion(options.ConnectionString);

                if (rightsAndVersion.Item1 == false)
                {
                    EnvDteHelper.ShowMessage(ReverseEngineerLocale.SqlServerNoViewDefinitionRights);
                }

                if (rightsAndVersion.Item2.Major < 11)
                {
                    EnvDteHelper.ShowMessage(String.Format(ReverseEngineerLocale.SQLServerVersionNotSupported, rightsAndVersion.Item2));
                }
            }
        }
        private DatabaseInfo GetDatabaseInfo(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            DatabaseInfo dbInfo = new DatabaseInfo();

            if (!string.IsNullOrEmpty(options.ConnectionString))
            {
                dbInfo.ConnectionString = options.ConnectionString;
                dbInfo.DatabaseType     = options.DatabaseType;
            }

            if (!string.IsNullOrEmpty(options.Dacpac))
            {
                dbInfo.DatabaseType = DatabaseType.SQLServerDacpac;
                if (options.Dacpac.EndsWith(".edmx", StringComparison.OrdinalIgnoreCase))
                {
                    dbInfo.DatabaseType = DatabaseType.Edmx;
                }
                dbInfo.ConnectionString  = $"Data Source=(local);Initial Catalog={Path.GetFileNameWithoutExtension(options.Dacpac)};Integrated Security=true;";
                options.ConnectionString = dbInfo.ConnectionString;
                options.DatabaseType     = dbInfo.DatabaseType;

                options.Dacpac = _package.Dte2.DTE.BuildSqlProj(options.Dacpac);
                if (string.IsNullOrEmpty(options.Dacpac))
                {
                    EnvDteHelper.ShowMessage(ReverseEngineerLocale.UnableToBuildSelectedDatabaseProject);
                    return(null);
                }
            }

            if (dbInfo.DatabaseType == DatabaseType.SQLCE35 ||
                dbInfo.DatabaseType == DatabaseType.SQLCE40 ||
                dbInfo.DatabaseType == DatabaseType.Undefined)
            {
                EnvDteHelper.ShowError($"{ReverseEngineerLocale.UnsupportedProvider}: {dbInfo.ServerVersion}");
                return(null);
            }

            return(dbInfo);
        }
Exemplo n.º 15
0
        public static async Task <ReverseEngineerResult> LaunchExternalRunnerAsync(ReverseEngineerOptions options, CodeGenerationMode codeGenerationMode)
        {
            var commandOptions = new ReverseEngineerCommandOptions
            {
                ConnectionString                   = options.ConnectionString,
                ContextClassName                   = options.ContextClassName,
                CustomReplacers                    = options.CustomReplacers,
                Dacpac                             = options.Dacpac,
                DatabaseType                       = options.DatabaseType,
                DefaultDacpacSchema                = options.DefaultDacpacSchema,
                IncludeConnectionString            = options.IncludeConnectionString,
                OutputPath                         = options.OutputPath,
                ContextNamespace                   = options.ContextNamespace,
                ModelNamespace                     = options.ModelNamespace,
                OutputContextPath                  = options.OutputContextPath,
                UseSchemaFolders                   = options.UseSchemaFolders,
                ProjectPath                        = options.ProjectPath,
                ProjectRootNamespace               = options.ProjectRootNamespace,
                SelectedHandlebarsLanguage         = options.SelectedHandlebarsLanguage,
                SelectedToBeGenerated              = options.SelectedToBeGenerated,
                Tables                             = options.Tables,
                UseDatabaseNames                   = options.UseDatabaseNames,
                UseFluentApiOnly                   = options.UseFluentApiOnly,
                UseHandleBars                      = options.UseHandleBars,
                UseInflector                       = options.UseInflector,
                UseLegacyPluralizer                = options.UseLegacyPluralizer,
                UseSpatial                         = options.UseSpatial,
                UseDbContextSplitting              = options.UseDbContextSplitting,
                UseNodaTime                        = options.UseNodaTime,
                UseBoolPropertiesWithoutDefaultSql = options.UseBoolPropertiesWithoutDefaultSql,
                UseNullableReferences              = options.UseNullableReferences,
                UseNoConstructor                   = options.UseNoConstructor,
                UseNoNavigations                   = options.UseNoNavigations,
                UseNoObjectFilter                  = options.UseNoObjectFilter,
            };

            var launcher = new EfRevEngLauncher(commandOptions, codeGenerationMode);

            return(await launcher.GetOutputAsync());
        }
Exemplo n.º 16
0
        private bool ChooseDataBaseConnectionByUiHint(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var databaseList = vsDataHelper.GetDataConnections(_package);

            if (databaseList != null && databaseList.Any())
            {
                var dataBaseInfo = databaseList.Values.FirstOrDefault(m => m.ConnectionName == options.UiHint);
                if (dataBaseInfo != null)
                {
                    options.ConnectionString = dataBaseInfo.ConnectionString;
                    options.DatabaseType     = dataBaseInfo.DatabaseType;
                    return(true);
                }
            }

            var dacpacList = _package.Dte2.DTE.GetDacpacFilesInActiveSolution(EnvDteHelper.GetProjectFilesInSolution(_package));

            if (dacpacList != null && dacpacList.Any())
            {
                if (!string.IsNullOrEmpty(options.UiHint) &&
                    options.UiHint.EndsWith(".sqlproj", StringComparison.OrdinalIgnoreCase))
                {
                    var candidate = dacpacList
                                    .Where(m => !string.IsNullOrWhiteSpace(m) && m.EndsWith(".sqlproj"))
                                    .FirstOrDefault(m => m.Equals(options.UiHint, StringComparison.OrdinalIgnoreCase));

                    if (candidate != null)
                    {
                        options.Dacpac = candidate;
                        return(true);
                    }
                }
            }

            return(false);
        }
        private async Task <DatabaseConnectionModel> GetDatabaseInfoAsync(ReverseEngineerOptions options)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var dbInfo = new DatabaseConnectionModel();

            if (!string.IsNullOrEmpty(options.ConnectionString))
            {
                dbInfo.ConnectionString = options.ConnectionString;
                dbInfo.DatabaseType     = options.DatabaseType;
            }

            if (!string.IsNullOrEmpty(options.Dacpac))
            {
                dbInfo.DatabaseType      = DatabaseType.SQLServerDacpac;
                dbInfo.ConnectionString  = $"Data Source=(local);Initial Catalog={Path.GetFileNameWithoutExtension(options.Dacpac)};Integrated Security=true;";
                options.ConnectionString = dbInfo.ConnectionString;
                options.DatabaseType     = dbInfo.DatabaseType;

                options.Dacpac = await EnvDTEExtensions.BuildSqlProjAsync(options.Dacpac);

                if (string.IsNullOrEmpty(options.Dacpac))
                {
                    VSHelper.ShowMessage(ReverseEngineerLocale.UnableToBuildSelectedDatabaseProject);
                    return(null);
                }
            }

            if (dbInfo.DatabaseType == DatabaseType.Undefined)
            {
                VSHelper.ShowError($"{ReverseEngineerLocale.UnsupportedProvider}");
                return(null);
            }

            return(dbInfo);
        }
Exemplo n.º 18
0
        private static async System.Threading.Tasks.Task InstallNuGetPackagesAsync(Project project, bool onlyGenerate, Tuple <bool, string> containsEfCoreReference, ReverseEngineerOptions options, bool forceEdit)
        {
            var nuGetHelper = new NuGetHelper();

            if (options.InstallNuGetPackage && (!onlyGenerate || forceEdit) &&
                await project.IsNetCore31OrHigherAsync() &&
                containsEfCoreReference != null)
            {
                await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.InstallingEFCoreProviderPackage);

                await nuGetHelper.InstallPackageAsync(containsEfCoreReference.Item2, project);
            }

            if (options.Tables.Any(t => t.ObjectType == ObjectType.Procedure) &&
                AdvancedOptions.Instance.DiscoverMultipleResultSets)
            {
                await nuGetHelper.InstallPackageAsync("Dapper", project);
            }
        }
        private bool ChooseDataBaseConnection(ReverseEngineerOptions options)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var databaseList = vsDataHelper.GetDataConnections(_package);
            var dacpacList   = _package.Dte2.DTE.GetDacpacFilesInActiveSolution(EnvDteHelper.GetProjectFilesInSolution(_package));

            var psd = _package.GetView <IPickServerDatabaseDialog>();

            if (databaseList != null && databaseList.Any())
            {
                psd.PublishConnections(databaseList.Select(m => new DatabaseConnectionModel
                {
                    ConnectionName   = m.Value.Caption,
                    ConnectionString = m.Value.ConnectionString,
                    DatabaseType     = m.Value.DatabaseType,
                    DataConnection   = m.Value.DataConnection,
                }));
            }

            if (dacpacList != null && dacpacList.Any())
            {
                psd.PublishDefinitions(dacpacList.Select(m => new DatabaseDefinitionModel
                {
                    FilePath = m
                }));
            }

            if (options.FilterSchemas && options.Schemas != null && options.Schemas.Any())
            {
                psd.PublishSchemas(options.Schemas);
            }

            psd.PublishCodeGenerationMode(options.CodeGenerationMode);

            if (!string.IsNullOrEmpty(options.UiHint))
            {
                psd.PublishUiHint(options.UiHint);
            }

            var pickDataSourceResult = psd.ShowAndAwaitUserResponse(true);

            if (!pickDataSourceResult.ClosedByOK)
            {
                return(false);
            }

            options.CodeGenerationMode = pickDataSourceResult.Payload.IncludeViews ? CodeGenerationMode.EFCore5 : CodeGenerationMode.EFCore3;
            options.FilterSchemas      = pickDataSourceResult.Payload.FilterSchemas;
            options.Schemas            = options.FilterSchemas ? pickDataSourceResult.Payload.Schemas?.ToList() : null;
            options.UiHint             = pickDataSourceResult.Payload.UiHint;
            options.Dacpac             = pickDataSourceResult.Payload.Definition?.FilePath;

            if (pickDataSourceResult.Payload.Connection != null)
            {
                options.ConnectionString = pickDataSourceResult.Payload.Connection.ConnectionString;
                options.DatabaseType     = pickDataSourceResult.Payload.Connection.DatabaseType;
            }

            return(true);
        }
Exemplo n.º 20
0
        public async System.Threading.Tasks.Task ReverseEngineerCodeFirstAsync(Project project, string optionsPath, bool onlyGenerate)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            try
            {
                if (await VSHelper.IsDebugModeAsync())
                {
                    VSHelper.ShowError(ReverseEngineerLocale.CannotGenerateCodeWhileDebugging);
                    return;
                }

                var renamingPath         = project.GetRenamingPath(optionsPath);
                var namingOptionsAndPath = CustomNameOptionsExtensions.TryRead(renamingPath, optionsPath);

                Tuple <bool, string> containsEfCoreReference = null;

                var options = ReverseEngineerOptionsExtensions.TryRead(optionsPath, Path.GetDirectoryName(project.FullPath));

                if (options == null)
                {
                    options = new ReverseEngineerOptions
                    {
                        ProjectRootNamespace = await project.GetAttributeAsync("RootNamespace"),
                    };
                }

                legacyDiscoveryObjects = options.Tables?.Where(t => t.UseLegacyResultSetDiscovery).Select(t => t.Name).ToList() ?? new List <string>();
                mappedTypes            = options.Tables?
                                         .Where(t => !string.IsNullOrEmpty(t.MappedType) && t.ObjectType == ObjectType.Procedure)
                                         .Select(m => new { m.Name, m.MappedType }).ToDictionary(m => m.Name, m => m.MappedType) ?? new Dictionary <string, string>();

                options.ProjectPath = Path.GetDirectoryName(project.FullPath);
                options.OptionsPath = Path.GetDirectoryName(optionsPath);

                bool forceEdit = false;

                if (onlyGenerate)
                {
                    forceEdit = !await ChooseDataBaseConnectionByUiHintAsync(options);

                    if (forceEdit)
                    {
                        await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.DatabaseConnectionNotFoundCannotRefresh);
                    }
                    else
                    {
                        var dbInfo = await GetDatabaseInfoAsync(options);

                        if (dbInfo == null)
                        {
                            return;
                        }

                        containsEfCoreReference     = new Tuple <bool, string>(true, null);
                        options.CustomReplacers     = namingOptionsAndPath.Item1;
                        options.InstallNuGetPackage = false;
                    }
                }

                if (!onlyGenerate || forceEdit)
                {
                    if (!await ChooseDataBaseConnectionAsync(options))
                    {
                        return;
                    }

                    await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.GettingReadyToConnect);

                    var dbInfo = await GetDatabaseInfoAsync(options);

                    if (dbInfo == null)
                    {
                        return;
                    }

                    VerifySQLServerRightsAndVersion(options);

                    await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.LoadingDatabaseObjects);

                    if (!await LoadDataBaseObjectsAsync(options, dbInfo, namingOptionsAndPath))
                    {
                        return;
                    }

                    await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.LoadingOptions);

                    containsEfCoreReference = await project.ContainsEfCoreReferenceAsync(options.DatabaseType);

                    options.InstallNuGetPackage = !containsEfCoreReference.Item1;

                    if (!await GetModelOptionsAsync(options, project.Name))
                    {
                        return;
                    }

                    await SaveOptionsAsync(project, optionsPath, options, new Tuple <List <Schema>, string>(options.CustomReplacers, namingOptionsAndPath.Item2));
                }

                await GenerateFilesAsync(project, options, containsEfCoreReference);

                await InstallNuGetPackagesAsync(project, onlyGenerate, containsEfCoreReference, options, forceEdit);

                var postRunFile = Path.Combine(Path.GetDirectoryName(optionsPath), "efpt.postrun.cmd");
                if (File.Exists(postRunFile))
                {
                    Process.Start($"\"{postRunFile}\"");
                }

                Telemetry.TrackEvent("PowerTools.ReverseEngineer");
            }
            catch (AggregateException ae)
            {
                foreach (var innerException in ae.Flatten().InnerExceptions)
                {
                    package.LogError(new List <string>(), innerException);
                }
            }
            catch (Exception exception)
            {
                package.LogError(new List <string>(), exception);
            }
        }
Exemplo n.º 21
0
        public async System.Threading.Tasks.Task ReverseEngineerCodeFirstAsync(Project project, string optionsPath, bool onlyGenerate)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            try
            {
                var dteH = new EnvDteHelper();

                if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug)
                {
                    EnvDteHelper.ShowError(ReverseEngineerLocale.CannotGenerateCodeWhileDebugging);
                    return;
                }

                var renamingPath         = project.GetRenamingPath(optionsPath);
                var namingOptionsAndPath = CustomNameOptionsExtensions.TryRead(renamingPath, optionsPath);

                Tuple <bool, string> containsEfCoreReference = null;

                var options = ReverseEngineerOptionsExtensions.TryRead(optionsPath);

                if (options == null)
                {
                    options = new ReverseEngineerOptions
                    {
                        ProjectRootNamespace = project.Properties.Item("DefaultNamespace").Value.ToString()
                    };
                }

                options.ProjectPath = project.Properties.Item("FullPath")?.Value.ToString();

                bool forceEdit = false;

                if (onlyGenerate)
                {
                    forceEdit = !ChooseDataBaseConnectionByUiHint(options);

                    if (forceEdit)
                    {
                        _package.Dte2.StatusBar.Text = ReverseEngineerLocale.DatabaseConnectionNotFoundCannotRefresh;
                    }
                    else
                    {
                        var dbInfo = GetDatabaseInfo(options);

                        if (dbInfo == null)
                        {
                            return;
                        }

                        containsEfCoreReference     = new Tuple <bool, string>(true, null);
                        options.CustomReplacers     = namingOptionsAndPath.Item1;
                        options.InstallNuGetPackage = false;
                    }
                }

                if (!onlyGenerate || forceEdit)
                {
                    if (!ChooseDataBaseConnection(options))
                    {
                        return;
                    }

                    _package.Dte2.StatusBar.Text = ReverseEngineerLocale.GettingReadyToConnect;

                    var dbInfo = GetDatabaseInfo(options);

                    if (dbInfo == null)
                    {
                        return;
                    }

                    _package.Dte2.StatusBar.Text = ReverseEngineerLocale.LoadingDatabaseObjects;

                    if (!await LoadDataBaseObjectsAsync(options, dbInfo, namingOptionsAndPath))
                    {
                        return;
                    }

                    _package.Dte2.StatusBar.Text = ReverseEngineerLocale.LoadingOptions;

                    containsEfCoreReference     = project.ContainsEfCoreReference(options.DatabaseType);
                    options.InstallNuGetPackage = !containsEfCoreReference.Item1;

                    if (!GetModelOptions(options, project.Name))
                    {
                        return;
                    }

                    SaveOptions(project, optionsPath, options, new Tuple <List <Schema>, string>(options.CustomReplacers, namingOptionsAndPath.Item2));
                }

                VerifySQLServerRightsAndVersion(options);

                await GenerateFilesAsync(project, options, containsEfCoreReference);

                if (options.InstallNuGetPackage && (!onlyGenerate || forceEdit) && project.IsNetCore31OrHigher())
                {
                    _package.Dte2.StatusBar.Text = ReverseEngineerLocale.InstallingEFCoreProviderPackage;
                    var nuGetHelper = new NuGetHelper();
                    await nuGetHelper.InstallPackageAsync(containsEfCoreReference.Item2, project);
                }

                Telemetry.TrackEvent("PowerTools.ReverseEngineer");
            }
            catch (AggregateException ae)
            {
                foreach (var innerException in ae.Flatten().InnerExceptions)
                {
                    _package.LogError(new List <string>(), innerException);
                }
            }
            catch (Exception exception)
            {
                _package.LogError(new List <string>(), exception);
            }
        }
Exemplo n.º 22
0
        private async System.Threading.Tasks.Task GenerateFilesAsync(Project project, ReverseEngineerOptions options, Tuple <bool, string> containsEfCoreReference)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var startTime = DateTime.Now;

            if (options.UseHandleBars)
            {
                var dropped = (DropTemplates(options.ProjectPath, options.CodeGenerationMode == CodeGenerationMode.EFCore5));
                if (dropped)
                {
                    project.ProjectItems.AddFromDirectory(Path.Combine(options.ProjectPath, "CodeTemplates"));
                }
            }

            options.UseNullableReferences = project.IsNetFramework() ? false : options.UseNullableReferences;

            _package.Dte2.StatusBar.Animate(true, _icon);
            _package.Dte2.StatusBar.Text = ReverseEngineerLocale.GeneratingCode;
            var revEngResult = await EfRevEngLauncher.LaunchExternalRunnerAsync(options, options.CodeGenerationMode);

            _package.Dte2.StatusBar.Animate(false, _icon);

            var  tfm           = project.Properties.Item("TargetFrameworkMoniker").Value.ToString();
            bool isNetStandard = tfm.Contains(".NETStandard,Version=v2.");

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 2)
            {
                if (!project.IsNetCore31OrHigher() && !isNetStandard)
                {
                    foreach (var filePath in revEngResult.EntityTypeFilePaths)
                    {
                        project.ProjectItems.AddFromFile(filePath);
                    }
                }
            }

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 1)
            {
                if (!project.IsNetCore31OrHigher() && !isNetStandard)
                {
                    foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                    {
                        project.ProjectItems.AddFromFile(filePath);
                    }

                    project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);
                }

                _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath);
            }

            var duration = DateTime.Now - startTime;

            var missingProviderPackage = containsEfCoreReference.Item1 ? null : containsEfCoreReference.Item2;

            if (options.InstallNuGetPackage || options.SelectedToBeGenerated == 2)
            {
                missingProviderPackage = null;
            }

            _package.Dte2.StatusBar.Text = ReverseEngineerLocale.ReportingResult;
            var errors = reverseEngineerHelper.ReportRevEngErrors(revEngResult, missingProviderPackage);

            _package.Dte2.StatusBar.Text = String.Format(ReverseEngineerLocale.ReverseEngineerCompleted, duration.ToString("h\\:mm\\:ss"));

            EnvDteHelper.ShowMessage(errors);

            if (revEngResult.EntityErrors.Count > 0)
            {
                _package.LogError(revEngResult.EntityErrors, null);
            }
            if (revEngResult.EntityWarnings.Count > 0)
            {
                _package.LogError(revEngResult.EntityWarnings, null);
            }
        }
Exemplo n.º 23
0
        private async System.Threading.Tasks.Task SaveOptionsAsync(Project project, string optionsPath, ReverseEngineerOptions options, Tuple <List <Schema>, string> renamingOptions)
        {
            if (File.Exists(optionsPath) && File.GetAttributes(optionsPath).HasFlag(FileAttributes.ReadOnly))
            {
                VSHelper.ShowError($"Unable to save options, the file is readonly: {optionsPath}");
                return;
            }

            if (!File.Exists(optionsPath + ".ignore"))
            {
                if (!AdvancedOptions.Instance.IncludeUiHintInConfig)
                {
                    options.UiHint = null;
                }

                foreach (var table in options.Tables)
                {
                    if (legacyDiscoveryObjects.Contains(table.Name))
                    {
                        table.UseLegacyResultSetDiscovery = true;
                    }

                    if (mappedTypes.ContainsKey(table.Name))
                    {
                        table.MappedType = mappedTypes[table.Name];
                    }
                }

                File.WriteAllText(optionsPath, options.Write(Path.GetDirectoryName(project.FullPath)), Encoding.UTF8);

                await project.AddExistingFilesAsync(new List <string> {
                    optionsPath
                }.ToArray());
            }

            if (renamingOptions.Item1 != null && !File.Exists(renamingOptions.Item2 + ".ignore") && renamingOptions.Item1.Count > 0)
            {
                if (File.Exists(renamingOptions.Item2) && File.GetAttributes(renamingOptions.Item2).HasFlag(FileAttributes.ReadOnly))
                {
                    VSHelper.ShowError($"Unable to save renaming options, the file is readonly: {renamingOptions.Item2}");
                    return;
                }

                File.WriteAllText(renamingOptions.Item2, CustomNameOptionsExtensions.Write(renamingOptions.Item1), Encoding.UTF8);
                await project.AddExistingFilesAsync(new List <string> {
                    renamingOptions.Item2
                }.ToArray());
            }
        }
        private bool GetModelOptions(ReverseEngineerOptions options, string projectName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var classBasis = VsDataHelper.GetDatabaseName(options.ConnectionString, options.DatabaseType);
            var model      = reverseEngineerHelper.GenerateClassName(classBasis) + "Context";

            if (string.IsNullOrEmpty(options.ContextClassName))
            {
                options.ContextClassName = model;
            }

            var presets = new ModelingOptionsModel
            {
                InstallNuGetPackage                = options.InstallNuGetPackage,
                ModelName                          = options.ContextClassName,
                ProjectName                        = projectName,
                Namespace                          = options.ProjectRootNamespace,
                DacpacPath                         = options.Dacpac,
                UseDataAnnotations                 = !options.UseFluentApiOnly,
                UseDatabaseNames                   = options.UseDatabaseNames,
                UsePluralizer                      = options.UseInflector,
                UseDbContextSplitting              = options.UseDbContextSplitting,
                UseHandlebars                      = options.UseHandleBars,
                SelectedHandlebarsLanguage         = options.SelectedHandlebarsLanguage,
                IncludeConnectionString            = options.IncludeConnectionString,
                OutputPath                         = options.OutputPath,
                OutputContextPath                  = options.OutputContextPath,
                ModelNamespace                     = options.ModelNamespace,
                ContextNamespace                   = options.ContextNamespace,
                SelectedToBeGenerated              = options.SelectedToBeGenerated,
                UseEf6Pluralizer                   = options.UseLegacyPluralizer,
                MapSpatialTypes                    = options.UseSpatial,
                MapNodaTimeTypes                   = options.UseNodaTime,
                UseBoolPropertiesWithoutDefaultSql = options.UseBoolPropertiesWithoutDefaultSql,
                UseNoConstructor                   = options.UseNoConstructor,
                UseNoNavigations                   = options.UseNoNavigations,
                UseNullableReferences              = options.UseNullableReferences,
                UseNoObjectFilter                  = options.UseNoObjectFilter,
            };

            var modelDialog = _package.GetView <IModelingOptionsDialog>()
                              .ApplyPresets(presets);

            _package.Dte2.StatusBar.Clear();

            var modelingOptionsResult = modelDialog.ShowAndAwaitUserResponse(true);

            if (!modelingOptionsResult.ClosedByOK)
            {
                return(false);
            }

            options.InstallNuGetPackage                = modelingOptionsResult.Payload.InstallNuGetPackage;
            options.UseFluentApiOnly                   = !modelingOptionsResult.Payload.UseDataAnnotations;
            options.ContextClassName                   = modelingOptionsResult.Payload.ModelName;
            options.OutputPath                         = modelingOptionsResult.Payload.OutputPath;
            options.OutputContextPath                  = modelingOptionsResult.Payload.OutputContextPath;
            options.ContextNamespace                   = modelingOptionsResult.Payload.ContextNamespace;
            options.ModelNamespace                     = modelingOptionsResult.Payload.ModelNamespace;
            options.ProjectRootNamespace               = modelingOptionsResult.Payload.Namespace;
            options.UseDatabaseNames                   = modelingOptionsResult.Payload.UseDatabaseNames;
            options.UseInflector                       = modelingOptionsResult.Payload.UsePluralizer;
            options.UseLegacyPluralizer                = modelingOptionsResult.Payload.UseEf6Pluralizer;
            options.UseSpatial                         = modelingOptionsResult.Payload.MapSpatialTypes;
            options.UseNodaTime                        = modelingOptionsResult.Payload.MapNodaTimeTypes;
            options.UseDbContextSplitting              = modelingOptionsResult.Payload.UseDbContextSplitting;
            options.UseHandleBars                      = modelingOptionsResult.Payload.UseHandlebars;
            options.SelectedHandlebarsLanguage         = modelingOptionsResult.Payload.SelectedHandlebarsLanguage;
            options.IncludeConnectionString            = modelingOptionsResult.Payload.IncludeConnectionString;
            options.SelectedToBeGenerated              = modelingOptionsResult.Payload.SelectedToBeGenerated;
            options.UseBoolPropertiesWithoutDefaultSql = modelingOptionsResult.Payload.UseBoolPropertiesWithoutDefaultSql;
            options.UseNullableReferences              = modelingOptionsResult.Payload.UseNullableReferences;
            options.UseNoConstructor                   = modelingOptionsResult.Payload.UseNoConstructor;
            options.UseNoNavigations                   = modelingOptionsResult.Payload.UseNoNavigations;
            options.UseNoObjectFilter                  = modelingOptionsResult.Payload.UseNoObjectFilter;

            return(true);
        }
        private void GenerateFiles(Project project, ReverseEngineerOptions options, Tuple <bool, string> containsEfCoreReference)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var startTime = DateTime.Now;

            if (options.UseHandleBars)
            {
                var dropped = (DropTemplates(options.ProjectPath, options.CodeGenerationMode == CodeGenerationMode.EFCore5));
                if (dropped)
                {
                    project.ProjectItems.AddFromDirectory(Path.Combine(options.ProjectPath, "CodeTemplates"));
                }
            }

            options.UseNullableReferences = project.IsNetFramework() ? false : options.UseNullableReferences;

            _package.Dte2.StatusBar.Animate(true, _icon);
            _package.Dte2.StatusBar.Text = ReverseEngineerLocale.GeneratingCode;
            var revEngResult = EfRevEngLauncher.LaunchExternalRunner(options, options.CodeGenerationMode == CodeGenerationMode.EFCore5);

            _package.Dte2.StatusBar.Animate(false, _icon);

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 2)
            {
                foreach (var filePath in revEngResult.EntityTypeFilePaths)
                {
                    project.ProjectItems.AddFromFile(filePath);
                }
            }

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 1)
            {
                foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                {
                    project.ProjectItems.AddFromFile(filePath);
                }

                project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);

                _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath);
            }

            var duration = DateTime.Now - startTime;

            var missingProviderPackage = containsEfCoreReference.Item1 ? null : containsEfCoreReference.Item2;

            if (options.InstallNuGetPackage || options.SelectedToBeGenerated == 2)
            {
                missingProviderPackage = null;
            }

            _package.Dte2.StatusBar.Text = ReverseEngineerLocale.ReportingResult;
            var errors = reverseEngineerHelper.ReportRevEngErrors(revEngResult, missingProviderPackage);

            _package.Dte2.StatusBar.Text = String.Format(ReverseEngineerLocale.ReverseEngineerCompleted, duration.ToString("h\\:mm\\:ss"));

            EnvDteHelper.ShowMessage(errors);

            if (revEngResult.EntityErrors.Count > 0)
            {
                _package.LogError(revEngResult.EntityErrors, null);
            }
            if (revEngResult.EntityWarnings.Count > 0)
            {
                _package.LogError(revEngResult.EntityWarnings, null);
            }
        }
        private async System.Threading.Tasks.Task SaveOptionsAsync(Project project, string optionsPath, ReverseEngineerOptions options, Tuple <List <Schema>, string> renamingOptions)
        {
            if (File.Exists(optionsPath) && File.GetAttributes(optionsPath).HasFlag(FileAttributes.ReadOnly))
            {
                //TODO Localize
                VSHelper.ShowError($"Unable to save options, the file is readonly: {optionsPath}");
                return;
            }

            if (!File.Exists(optionsPath + ".ignore"))
            {
                if (!Properties.Settings.Default.IncludeUiHintInConfig)
                {
                    options.UiHint = null;
                }

                File.WriteAllText(optionsPath, options.Write(Path.GetDirectoryName(project.FullPath)), Encoding.UTF8);

                await project.AddExistingFilesAsync(new List <string> {
                    optionsPath
                }.ToArray());
            }

            if (renamingOptions.Item1 != null && !File.Exists(renamingOptions.Item2 + ".ignore") && renamingOptions.Item1.Count() > 0)
            {
                if (File.Exists(renamingOptions.Item2) && File.GetAttributes(renamingOptions.Item2).HasFlag(FileAttributes.ReadOnly))
                {
                    //TODO Localize
                    VSHelper.ShowError($"Unable to save renaming options, the file is readonly: {renamingOptions.Item2}");
                    return;
                }

                File.WriteAllText(renamingOptions.Item2, CustomNameOptionsExtensions.Write(renamingOptions.Item1), Encoding.UTF8);
                await project.AddExistingFilesAsync(new List <string> {
                    renamingOptions.Item2
                }.ToArray());
            }
        }
Exemplo n.º 27
0
        private async System.Threading.Tasks.Task GenerateFilesAsync(Project project, ReverseEngineerOptions options, Tuple <bool, string> containsEfCoreReference)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var startTime = DateTime.Now;

            if (options.UseHandleBars)
            {
                DropTemplates(options.OptionsPath, options.CodeGenerationMode);
            }

            options.UseNullableReferences = !await project.IsLegacyAsync() && options.UseNullableReferences;

            await VS.StatusBar.ShowProgressAsync(ReverseEngineerLocale.GeneratingCode, 1, 3);

            var revEngResult = await EfRevEngLauncher.LaunchExternalRunnerAsync(options, options.CodeGenerationMode, project);

            await VS.StatusBar.ShowProgressAsync(ReverseEngineerLocale.GeneratingCode, 2, 3);

            var tfm = await project.GetAttributeAsync("TargetFrameworkMoniker");

            bool isNetStandard = tfm?.Contains(".NETStandard,Version=v2.") ?? false;

            if ((options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 2) &&
                !await project.IsNetCore31OrHigherAsync() && !isNetStandard)
            {
                foreach (var filePath in revEngResult.EntityTypeFilePaths)
                {
                    await project.AddExistingFilesAsync(new List <string> {
                        filePath
                    }.ToArray());
                }
            }

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 1)
            {
                if (!await project.IsNetCore31OrHigherAsync() && !isNetStandard)
                {
                    foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                    {
                        await project.AddExistingFilesAsync(new List <string> {
                            filePath
                        }.ToArray());
                    }

                    await project.AddExistingFilesAsync(new List <string> {
                        revEngResult.ContextFilePath
                    }.ToArray());
                }

                if (AdvancedOptions.Instance.OpenGeneratedDbContext)
                {
                    var readmeName = "PowerToolsReadMe.txt";
                    var finalText  = reverseEngineerHelper.GetReadMeText(options, File.ReadAllText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), readmeName), Encoding.UTF8));
                    var readmePath = Path.Combine(Path.GetTempPath(), readmeName);

                    File.WriteAllText(readmePath, finalText, Encoding.UTF8);

                    await VS.Documents.OpenAsync(readmePath);

                    await VS.Documents.OpenAsync(revEngResult.ContextFilePath);
                }
            }

            await VS.StatusBar.ShowProgressAsync(ReverseEngineerLocale.GeneratingCode, 3, 3);

            var duration = DateTime.Now - startTime;

            var missingProviderPackage = containsEfCoreReference.Item1 ? null : containsEfCoreReference.Item2;

            if (options.InstallNuGetPackage || options.SelectedToBeGenerated == 2)
            {
                missingProviderPackage = null;
            }

            var errors = reverseEngineerHelper.ReportRevEngErrors(revEngResult, missingProviderPackage);

            await VS.StatusBar.ShowMessageAsync(string.Format(ReverseEngineerLocale.ReverseEngineerCompleted, duration.ToString("h\\:mm\\:ss")));

            if (errors != ReverseEngineerLocale.ModelGeneratedSuccesfully + Environment.NewLine)
            {
                VSHelper.ShowMessage(errors);
            }

            if (revEngResult.EntityErrors.Count > 0)
            {
                package.LogError(revEngResult.EntityErrors, null);
            }

            if (revEngResult.EntityWarnings.Count > 0)
            {
                package.LogError(revEngResult.EntityWarnings, null);
            }

            Telemetry.TrackFrameworkUse(nameof(ReverseEngineerHandler), options.CodeGenerationMode);
        }
        private async System.Threading.Tasks.Task GenerateFilesAsync(Project project, ReverseEngineerOptions options, Tuple <bool, string> containsEfCoreReference)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var startTime = DateTime.Now;

            if (options.UseHandleBars)
            {
                DropTemplates(options.OptionsPath, options.CodeGenerationMode);
            }

            options.UseNullableReferences = await project.IsNetFrameworkAsync() ? false : options.UseNullableReferences;

            //TODO Disable for now - see #1164  await SetNullableAsync(options, project);

            await VS.StatusBar.StartAnimationAsync(StatusAnimation.Build);

            await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.GeneratingCode);

            var revEngResult = await EfRevEngLauncher.LaunchExternalRunnerAsync(options, options.CodeGenerationMode);

            await VS.StatusBar.EndAnimationAsync(StatusAnimation.Build);

            var tfm = await project.GetAttributeAsync("TargetFrameworkMoniker");

            bool isNetStandard = tfm?.Contains(".NETStandard,Version=v2.") ?? false;

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 2)
            {
                if (!await project.IsNetCore31OrHigherAsync() && !isNetStandard)
                {
                    foreach (var filePath in revEngResult.EntityTypeFilePaths)
                    {
                        await project.AddExistingFilesAsync(new List <string> {
                            filePath
                        }.ToArray());
                    }
                }
            }

            if (options.SelectedToBeGenerated == 0 || options.SelectedToBeGenerated == 1)
            {
                if (!await project.IsNetCore31OrHigherAsync() && !isNetStandard)
                {
                    foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                    {
                        await project.AddExistingFilesAsync(new List <string> {
                            filePath
                        }.ToArray());
                    }
                    await project.AddExistingFilesAsync(new List <string> {
                        revEngResult.ContextFilePath
                    }.ToArray());
                }

                if (Properties.Settings.Default.OpenGeneratedDbContext)
                {
                    await VS.Documents.OpenAsync(revEngResult.ContextFilePath);
                }
            }

            var duration = DateTime.Now - startTime;

            var missingProviderPackage = containsEfCoreReference.Item1 ? null : containsEfCoreReference.Item2;

            if (options.InstallNuGetPackage || options.SelectedToBeGenerated == 2)
            {
                missingProviderPackage = null;
            }

            await VS.StatusBar.ShowMessageAsync(ReverseEngineerLocale.ReportingResult);

            var errors = reverseEngineerHelper.ReportRevEngErrors(revEngResult, missingProviderPackage);

            await VS.StatusBar.ShowMessageAsync(string.Format(ReverseEngineerLocale.ReverseEngineerCompleted, duration.ToString("h\\:mm\\:ss")));

            if (errors != ReverseEngineerLocale.ModelGeneratedSuccesfully + Environment.NewLine)
            {
                VSHelper.ShowMessage(errors);
            }

            if (revEngResult.EntityErrors.Count > 0)
            {
                _package.LogError(revEngResult.EntityErrors, null);
            }
            if (revEngResult.EntityWarnings.Count > 0)
            {
                _package.LogError(revEngResult.EntityWarnings, null);
            }
        }
        public async System.Threading.Tasks.Task ReverseEngineerCodeFirstAsync(Project project)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            try
            {
                var    dteH         = new EnvDteHelper();
                string dacpacSchema = null;

                if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug)
                {
                    EnvDteHelper.ShowError("Cannot generate code while debugging");
                    return;
                }

                var projectPath  = project.Properties.Item("FullPath")?.Value.ToString();
                var optionsPaths = project.GetConfigFiles();
                var optionsPath  = optionsPaths.First();
                var renamingPath = project.GetRenamingPath();

                if (optionsPaths.Count > 1)
                {
                    var pcd = _package.GetView <IPickConfigDialog>();
                    pcd.PublishConfigurations(optionsPaths.Select(m => new ConfigModel
                    {
                        ConfigPath  = m,
                        ProjectPath = projectPath
                    }));

                    var pickConfigResult = pcd.ShowAndAwaitUserResponse(true);
                    if (!pickConfigResult.ClosedByOK)
                    {
                        return;
                    }

                    optionsPath = pickConfigResult.Payload.ConfigPath;
                }

                var databaseList = VsDataHelper.GetDataConnections(_package);
                var dacpacList   = _package.Dte2.DTE.GetDacpacFilesInActiveSolution(EnvDteHelper.GetProjectFilesInSolution(_package));
                var options      = ReverseEngineerOptionsExtensions.TryRead(optionsPath);

                var psd = _package.GetView <IPickServerDatabaseDialog>();

                if (databaseList != null && databaseList.Any())
                {
                    psd.PublishConnections(databaseList.Select(m => new DatabaseConnectionModel
                    {
                        ConnectionName   = m.Value.Caption,
                        ConnectionString = m.Value.ConnectionString,
                        DatabaseType     = m.Value.DatabaseType,
                        DataConnection   = m.Value.DataConnection,
                    }));
                }

                if (dacpacList != null && dacpacList.Any())
                {
                    psd.PublishDefinitions(dacpacList.Select(m => new DatabaseDefinitionModel
                    {
                        FilePath = m
                    }));
                }

                if (options != null)
                {
                    if (options.FilterSchemas && options.Schemas != null && options.Schemas.Any())
                    {
                        psd.PublishSchemas(options.Schemas);
                    }

                    psd.PublishCodeGenerationMode(options.CodeGenerationMode);

                    if (!string.IsNullOrEmpty(options.UiHint))
                    {
                        psd.PublishUiHint(options.UiHint);
                    }
                }

                var pickDataSourceResult = psd.ShowAndAwaitUserResponse(true);
                if (!pickDataSourceResult.ClosedByOK)
                {
                    return;
                }

                var useEFCore5    = pickDataSourceResult.Payload.IncludeViews;
                var filterSchemas = pickDataSourceResult.Payload.FilterSchemas;
                var schemas       = filterSchemas ? pickDataSourceResult.Payload.Schemas : null;

                _package.Dte2.StatusBar.Text = "Getting ready to connect...";

                DatabaseInfo dbInfo = null;
                if (pickDataSourceResult.Payload.Connection != null)
                {
                    dbInfo = new DatabaseInfo
                    {
                        ConnectionString = pickDataSourceResult.Payload.Connection.ConnectionString,
                        Caption          = pickDataSourceResult.Payload.Connection.ConnectionName,
                        DatabaseType     = pickDataSourceResult.Payload.Connection.DatabaseType,
                        DataConnection   = pickDataSourceResult.Payload.Connection.DataConnection,
                    };
                }
                var dacpacPath = pickDataSourceResult.Payload.Definition?.FilePath;

                if (dbInfo == null)
                {
                    dbInfo = new DatabaseInfo();
                }

                if (!string.IsNullOrEmpty(dacpacPath))
                {
                    dbInfo.DatabaseType     = DatabaseType.SQLServerDacpac;
                    dbInfo.ConnectionString = $"Data Source=(local);Initial Catalog={Path.GetFileNameWithoutExtension(dacpacPath)};Integrated Security=true;";
                    dacpacPath = _package.Dte2.DTE.BuildSqlProj(dacpacPath);
                    if (string.IsNullOrEmpty(dacpacPath))
                    {
                        EnvDteHelper.ShowMessage("Unable to build selected Database Project");
                        return;
                    }
                }

                if (dbInfo.DatabaseType == DatabaseType.SQLCE35 ||
                    dbInfo.DatabaseType == DatabaseType.SQLCE40 ||
                    dbInfo.DatabaseType == DatabaseType.Undefined)
                {
                    EnvDteHelper.ShowError($"Unsupported provider: {dbInfo.ServerVersion}");
                    return;
                }

                _package.Dte2.StatusBar.Text = "Loading database objects...";
                object icon = (short)Microsoft.VisualStudio.Shell.Interop.Constants.SBAI_Build;
                _package.Dte2.StatusBar.Animate(true, icon);
                var predefinedTables = !string.IsNullOrEmpty(dacpacPath)
                                           ? await GetDacpacTablesAsync(dacpacPath, useEFCore5)
                                           : await GetTablesAsync(dbInfo, useEFCore5, schemas);

                _package.Dte2.StatusBar.Animate(false, icon);

                var preselectedTables = new List <SerializationTableModel>();
                if (options != null)
                {
                    dacpacSchema = options.DefaultDacpacSchema;
                    if (options.Tables.Count > 0)
                    {
                        var normalizedTables = reverseEngineerHelper.NormalizeTables(options.Tables, dbInfo.DatabaseType == DatabaseType.SQLServer);
                        preselectedTables.AddRange(normalizedTables);
                    }
                }

                var namingOptionsAndPath = CustomNameOptionsExtensions.TryRead(renamingPath, optionsPath);

                _package.Dte2.StatusBar.Clear();

                var ptd = _package.GetView <IPickTablesDialog>()
                          .AddTables(predefinedTables, namingOptionsAndPath.Item1)
                          .PreselectTables(preselectedTables);

                var pickTablesResult = ptd.ShowAndAwaitUserResponse(true);
                if (!pickTablesResult.ClosedByOK)
                {
                    return;
                }

                _package.Dte2.StatusBar.Text = "Loading options...";

                var classBasis    = VsDataHelper.GetDatabaseName(dbInfo.ConnectionString, dbInfo.DatabaseType);
                var model         = reverseEngineerHelper.GenerateClassName(classBasis) + "Context";
                var packageResult = project.ContainsEfCoreReference(dbInfo.DatabaseType);

                var presets = new ModelingOptionsModel
                {
                    InstallNuGetPackage = !packageResult.Item1,
                    ModelName           = options != null ? options.ContextClassName : model,
                    ProjectName         = project.Name,
                    Namespace           = options != null ? options.ProjectRootNamespace : project.Properties.Item("DefaultNamespace").Value.ToString(),
                    DacpacPath          = dacpacPath,
                };
                if (options != null)
                {
                    presets.UseDataAnnotations         = !options.UseFluentApiOnly;
                    presets.UseDatabaseNames           = options.UseDatabaseNames;
                    presets.UsePluralizer              = options.UseInflector;
                    presets.UseDbContextSplitting      = options.UseDbContextSplitting;
                    presets.UseHandlebars              = options.UseHandleBars;
                    presets.SelectedHandlebarsLanguage = options.SelectedHandlebarsLanguage;
                    presets.IncludeConnectionString    = options.IncludeConnectionString;
                    presets.ModelName             = options.ContextClassName;
                    presets.Namespace             = options.ProjectRootNamespace;
                    presets.OutputPath            = options.OutputPath;
                    presets.OutputContextPath     = options.OutputContextPath;
                    presets.ModelNamespace        = options.ModelNamespace;
                    presets.ContextNamespace      = options.ContextNamespace;
                    presets.SelectedToBeGenerated = options.SelectedToBeGenerated;
                    presets.DacpacPath            = options.Dacpac;
                    presets.UseEf6Pluralizer      = options.UseLegacyPluralizer;
                    presets.MapSpatialTypes       = options.UseSpatial;
                    presets.MapNodaTimeTypes      = options.UseNodaTime;
                    presets.UseBoolPropertiesWithoutDefaultSql = options.UseBoolPropertiesWithoutDefaultSql;
                    presets.UseNoConstructor      = options.UseNoConstructor;
                    presets.UseNoNavigations      = options.UseNoNavigations;
                    presets.UseNullableReferences = options.UseNullableReferences;
                }

                var modelDialog = _package.GetView <IModelingOptionsDialog>()
                                  .ApplyPresets(presets);

                _package.Dte2.StatusBar.Clear();

                var modelingOptionsResult = modelDialog.ShowAndAwaitUserResponse(true);
                if (!modelingOptionsResult.ClosedByOK)
                {
                    return;
                }

                options = new ReverseEngineerOptions
                {
                    UseFluentApiOnly                   = !modelingOptionsResult.Payload.UseDataAnnotations,
                    ConnectionString                   = dbInfo.ConnectionString,
                    ContextClassName                   = modelingOptionsResult.Payload.ModelName,
                    DatabaseType                       = dbInfo.DatabaseType,
                    ProjectPath                        = projectPath,
                    OutputPath                         = modelingOptionsResult.Payload.OutputPath,
                    OutputContextPath                  = modelingOptionsResult.Payload.OutputContextPath,
                    ContextNamespace                   = modelingOptionsResult.Payload.ContextNamespace,
                    ModelNamespace                     = modelingOptionsResult.Payload.ModelNamespace,
                    ProjectRootNamespace               = modelingOptionsResult.Payload.Namespace,
                    UseDatabaseNames                   = modelingOptionsResult.Payload.UseDatabaseNames,
                    UseInflector                       = modelingOptionsResult.Payload.UsePluralizer,
                    UseLegacyPluralizer                = modelingOptionsResult.Payload.UseEf6Pluralizer,
                    UseSpatial                         = modelingOptionsResult.Payload.MapSpatialTypes,
                    UseNodaTime                        = modelingOptionsResult.Payload.MapNodaTimeTypes,
                    UseDbContextSplitting              = modelingOptionsResult.Payload.UseDbContextSplitting,
                    UseHandleBars                      = modelingOptionsResult.Payload.UseHandlebars,
                    SelectedHandlebarsLanguage         = modelingOptionsResult.Payload.SelectedHandlebarsLanguage,
                    IncludeConnectionString            = modelingOptionsResult.Payload.IncludeConnectionString,
                    SelectedToBeGenerated              = modelingOptionsResult.Payload.SelectedToBeGenerated,
                    UseBoolPropertiesWithoutDefaultSql = modelingOptionsResult.Payload.UseBoolPropertiesWithoutDefaultSql,
                    UseNullableReferences              = modelingOptionsResult.Payload.UseNullableReferences,
                    UseNoConstructor                   = modelingOptionsResult.Payload.UseNoConstructor,
                    UseNoNavigations                   = modelingOptionsResult.Payload.UseNoNavigations,
                    Dacpac = dacpacPath,
                    DefaultDacpacSchema = dacpacSchema,
                    Tables             = pickTablesResult.Payload.Objects.ToList(),
                    CustomReplacers    = pickTablesResult.Payload.CustomReplacers.ToList(),
                    FilterSchemas      = filterSchemas,
                    Schemas            = schemas?.ToList(),
                    CodeGenerationMode = pickDataSourceResult.Payload.IncludeViews ? CodeGenerationMode.EFCore5 : CodeGenerationMode.EFCore3,
                    UiHint             = pickDataSourceResult.Payload.UiHint,
                };

                if (options.DatabaseType == DatabaseType.SQLServer &&
                    string.IsNullOrEmpty(options.Dacpac))
                {
                    var rightsAndVersion = reverseEngineerHelper.HasSqlServerViewDefinitionRightsAndVersion(options.ConnectionString);

                    if (rightsAndVersion.Item1 == false)
                    {
                        EnvDteHelper.ShowMessage("The SQL Server user does not have 'VIEW DEFINITION' rights, default constraints may not be available.");
                    }

                    if (rightsAndVersion.Item2.Major < 11)
                    {
                        EnvDteHelper.ShowMessage($"SQL Server version {rightsAndVersion.Item2} may not be supported.");
                    }
                }

                if (modelingOptionsResult.Payload.UseHandlebars)
                {
                    var dropped = (DropTemplates(projectPath, useEFCore5));
                    if (dropped)
                    {
                        project.ProjectItems.AddFromDirectory(Path.Combine(projectPath, "CodeTemplates"));
                    }
                }

                var startTime = DateTime.Now;

                _package.Dte2.StatusBar.Animate(true, icon);
                _package.Dte2.StatusBar.Text = "Generating code...";
                var revEngResult = EfRevEngLauncher.LaunchExternalRunner(options, useEFCore5);
                _package.Dte2.StatusBar.Animate(false, icon);
                if (modelingOptionsResult.Payload.SelectedToBeGenerated == 0 || modelingOptionsResult.Payload.SelectedToBeGenerated == 2)
                {
                    foreach (var filePath in revEngResult.EntityTypeFilePaths)
                    {
                        project.ProjectItems.AddFromFile(filePath);
                    }

                    if (modelingOptionsResult.Payload.SelectedToBeGenerated == 2)
                    {
                        if (File.Exists(revEngResult.ContextFilePath))
                        {
                            File.Delete(revEngResult.ContextFilePath);
                        }
                        foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                        {
                            if (File.Exists(filePath))
                            {
                                File.Delete(filePath);
                            }
                        }
                    }
                }

                if (modelingOptionsResult.Payload.SelectedToBeGenerated == 0 || modelingOptionsResult.Payload.SelectedToBeGenerated == 1)
                {
                    foreach (var filePath in revEngResult.ContextConfigurationFilePaths)
                    {
                        project.ProjectItems.AddFromFile(filePath);
                    }
                    project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);

                    _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath);

                    if (modelingOptionsResult.Payload.SelectedToBeGenerated == 1)
                    {
                        foreach (var filePath in revEngResult.EntityTypeFilePaths)
                        {
                            if (File.Exists(filePath))
                            {
                                File.Delete(filePath);
                            }
                        }
                    }
                }

                var duration = DateTime.Now - startTime;

                var missingProviderPackage = packageResult.Item1 ? null : packageResult.Item2;
                if (modelingOptionsResult.Payload.InstallNuGetPackage || modelingOptionsResult.Payload.SelectedToBeGenerated == 2)
                {
                    missingProviderPackage = null;
                }

                _package.Dte2.StatusBar.Text = "Reporting result...";
                var errors = reverseEngineerHelper.ReportRevEngErrors(revEngResult, missingProviderPackage);

                SaveOptions(project, optionsPath, options, new Tuple <List <Schema>, string>(pickTablesResult.Payload.CustomReplacers.ToList(), namingOptionsAndPath.Item2));

                if (modelingOptionsResult.Payload.InstallNuGetPackage)
                {
                    _package.Dte2.StatusBar.Text = "Installing EF Core provider package";
                    var nuGetHelper = new NuGetHelper();
                    await nuGetHelper.InstallPackageAsync(packageResult.Item2, project);
                }

                _package.Dte2.StatusBar.Text = $"Reverse engineer completed in {duration:h\\:mm\\:ss}";

                EnvDteHelper.ShowMessage(errors);

                if (revEngResult.EntityErrors.Count > 0)
                {
                    _package.LogError(revEngResult.EntityErrors, null);
                }
                if (revEngResult.EntityWarnings.Count > 0)
                {
                    _package.LogError(revEngResult.EntityWarnings, null);
                }
                Telemetry.TrackEvent("PowerTools.ReverseEngineer");
            }
            catch (AggregateException ae)
            {
                foreach (var innerException in ae.Flatten().InnerExceptions)
                {
                    _package.LogError(new List <string>(), innerException);
                }
            }
            catch (Exception exception)
            {
                _package.LogError(new List <string>(), exception);
            }
        }