public async void ReverseEngineerCodeFirst(Project project) { try { var dteH = new EnvDteHelper(); var revEng = new EfCoreReverseEngineer(); string dacpacSchema = null; if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug) { EnvDteHelper.ShowError("Cannot generate code while debugging"); return; } var startTime = DateTime.Now; var projectPath = project.Properties.Item("FullPath").Value.ToString(); var optionsPath = Path.Combine(projectPath, "efpt.config.json"); var renamingPath = Path.Combine(projectPath, "efpt.renaming.json"); var databaseList = EnvDteHelper.GetDataConnections(_package); var dacpacList = _package.Dte2.DTE.GetDacpacFilesInActiveSolution(); 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 })); } if (dacpacList != null && dacpacList.Any()) { psd.PublishDefinitions(dacpacList.Select(m => new DatabaseDefinitionModel { FilePath = m })); } var pickDataSourceResult = psd.ShowAndAwaitUserResponse(true); if (!pickDataSourceResult.ClosedByOK) { return; } _package.Dte2.StatusBar.Text = "Loading schema information..."; // Reload the database list, in case the user has added a new database in the dialog databaseList = EnvDteHelper.GetDataConnections(_package); DatabaseInfo dbInfo = null; if (pickDataSourceResult.Payload.Connection != null) { dbInfo = databaseList.Single(m => m.Value.ConnectionString == pickDataSourceResult.Payload.Connection?.ConnectionString).Value; } var dacpacPath = pickDataSourceResult.Payload.Definition?.FilePath; if (dbInfo == null) { dbInfo = new DatabaseInfo(); } if (!string.IsNullOrEmpty(dacpacPath)) { dbInfo.DatabaseType = DatabaseType.SQLServer; dbInfo.ConnectionString = "Data Source=.;Initial Catalog=" + Path.GetFileNameWithoutExtension(dacpacPath); dacpacPath = _package.Dte2.DTE.BuildSqlProj(dacpacPath); if (string.IsNullOrEmpty(dacpacPath)) { EnvDteHelper.ShowMessage("Unable to build selected Database Project"); return; } } if (dbInfo.DatabaseType == DatabaseType.SQLCE35) { EnvDteHelper.ShowError($"Unsupported provider: {dbInfo.ServerVersion}"); return; } var options = ReverseEngineerOptionsExtensions.TryRead(optionsPath); var predefinedTables = !string.IsNullOrEmpty(dacpacPath) ? revEng.GetDacpacTables(dacpacPath) : GetTablesFromRepository(dbInfo); var preselectedTables = new List <TableInformationModel>(); if (options != null) { dacpacSchema = options.DefaultDacpacSchema; if (options.Tables.Count > 0) { preselectedTables.AddRange(options.Tables); } } var ptd = _package.GetView <IPickTablesDialog>() .AddTables(predefinedTables) .PreselectTables(preselectedTables); var customNameOptions = CustomNameOptionsExtensions.TryRead(renamingPath); var pickTablesResult = ptd.ShowAndAwaitUserResponse(true); if (!pickTablesResult.ClosedByOK) { return; } var classBasis = string.Empty; if (dbInfo.DatabaseType == DatabaseType.Npgsql) { classBasis = EnvDteHelper.GetNpgsqlDatabaseName(dbInfo.ConnectionString); } else if (dbInfo.DatabaseType == DatabaseType.Mysql) { classBasis = EnvDteHelper.GetMysqlDatabaseName(dbInfo.ConnectionString); } else { classBasis = RepositoryHelper.GetClassBasis(dbInfo.ConnectionString, dbInfo.DatabaseType); } var model = revEng.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.UseHandelbars = options.UseHandleBars; presets.SelectedHandlebarsLanguage = options.SelectedHandlebarsLanguage; presets.ReplaceId = options.IdReplace; presets.DoNotCombineNamespace = options.DoNotCombineNamespace; presets.IncludeConnectionString = options.IncludeConnectionString; presets.ModelName = options.ContextClassName; presets.Namespace = options.ProjectRootNamespace; presets.OutputPath = options.OutputPath; presets.SelectedToBeGenerated = options.SelectedToBeGenerated; } var modelDialog = _package.GetView <IModelingOptionsDialog>() .ApplyPresets(presets); _package.Dte2.StatusBar.Text = "Getting options..."; var modelingOptionsResult = modelDialog.ShowAndAwaitUserResponse(true); if (!modelingOptionsResult.ClosedByOK) { return; } options = new ReverseEngineerOptions { UseFluentApiOnly = !modelingOptionsResult.Payload.UseDataAnnotations, ConnectionString = dbInfo.ConnectionString, ContextClassName = modelingOptionsResult.Payload.ModelName, DatabaseType = (ReverseEngineer20.DatabaseType)dbInfo.DatabaseType, ProjectPath = projectPath, OutputPath = modelingOptionsResult.Payload.OutputPath, ProjectRootNamespace = modelingOptionsResult.Payload.Namespace, UseDatabaseNames = modelingOptionsResult.Payload.UseDatabaseNames, UseInflector = modelingOptionsResult.Payload.UsePluralizer, UseLegacyPluralizer = options?.UseLegacyPluralizer ?? false, IdReplace = modelingOptionsResult.Payload.ReplaceId, DoNotCombineNamespace = modelingOptionsResult.Payload.DoNotCombineNamespace, UseHandleBars = modelingOptionsResult.Payload.UseHandelbars, SelectedHandlebarsLanguage = modelingOptionsResult.Payload.SelectedHandlebarsLanguage, IncludeConnectionString = modelingOptionsResult.Payload.IncludeConnectionString, SelectedToBeGenerated = modelingOptionsResult.Payload.SelectedToBeGenerated, Dacpac = dacpacPath, DefaultDacpacSchema = dacpacSchema, Tables = pickTablesResult.Payload.ToList(), CustomReplacers = customNameOptions }; _package.Dte2.StatusBar.Text = "Generating code..."; var tfm = project.Properties.Item("TargetFrameworkMoniker").Value.ToString(); bool isNetStandard = tfm.Contains(".NETStandard,Version=v2.0"); if (modelingOptionsResult.Payload.UseHandelbars) { var dropped = (DropTemplates(projectPath)); if (dropped && !project.IsNetCore() && !isNetStandard) { project.ProjectItems.AddFromDirectory(Path.Combine(projectPath, "CodeTemplates")); } } var revEngResult = revEng.GenerateFiles(options); 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); } } } if (modelingOptionsResult.Payload.SelectedToBeGenerated == 0 || modelingOptionsResult.Payload.SelectedToBeGenerated == 1) { project.ProjectItems.AddFromFile(revEngResult.ContextFilePath); if (!project.IsNetCore() && !isNetStandard) { _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 missingProviderPackage = packageResult.Item1 ? null : packageResult.Item2; if (modelingOptionsResult.Payload.InstallNuGetPackage || modelingOptionsResult.Payload.SelectedToBeGenerated == 2) { missingProviderPackage = null; } _package.Dte2.StatusBar.Text = "Reporting result..."; var errors = ReportRevEngErrors(revEngResult, missingProviderPackage); SaveOptions(project, optionsPath, options); if (modelingOptionsResult.Payload.InstallNuGetPackage) { _package.Dte2.StatusBar.Text = "Installing EF Core provider package"; var nuGetHelper = new NuGetHelper(); await nuGetHelper.InstallPackageAsync(packageResult.Item2, project); } var duration = DateTime.Now - startTime; _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); } }
public async void ReverseEngineerCodeFirst(Project project) { try { var dteH = new EnvDteHelper(); var revEng = new EfCoreReverseEngineer(); string dacpacSchema = null; if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug) { EnvDteHelper.ShowError("Cannot generate code while debugging"); return; } var startTime = DateTime.Now; var projectPath = project.Properties.Item("FullPath").Value.ToString(); var optionsPath = Path.Combine(projectPath, "efpt.config.json"); var databaseList = EnvDteHelper.GetDataConnections(_package); var dacpacList = _package.Dte2.DTE.GetDacpacFilesInActiveSolution(); var psd = new PickServerDatabaseDialog(databaseList, _package, dacpacList); if (psd.ShowModal() != true) { return; } _package.Dte2.StatusBar.Text = "Loading schema information..."; var dbInfo = psd.SelectedDatabase.Value; var dacpacPath = psd.DacpacPath; if (dbInfo == null) { dbInfo = new DatabaseInfo(); } if (!string.IsNullOrEmpty(dacpacPath)) { dbInfo.DatabaseType = DatabaseType.SQLServer; dbInfo.ConnectionString = "Data Source=.;Initial Catalog=" + Path.GetFileNameWithoutExtension(dacpacPath); dacpacPath = _package.Dte2.DTE.BuildSqlProj(dacpacPath); if (string.IsNullOrEmpty(dacpacPath)) { EnvDteHelper.ShowMessage("Unable to build selected Database Project"); return; } } if (dbInfo.DatabaseType == DatabaseType.SQLCE35) { EnvDteHelper.ShowError($"Unsupported provider: {dbInfo.ServerVersion}"); return; } var ptd = new PickTablesDialog { IncludeTables = true }; if (!string.IsNullOrEmpty(dacpacPath)) { ptd.Tables = revEng.GetDacpacTableNames(dacpacPath); } else { ptd.Tables = GetTablesFromRepository(dbInfo); } var options = ReverseEngineerOptionsExtensions.TryRead(optionsPath); if (options != null) { dacpacSchema = options.DefaultDacpacSchema; if (options.Tables.Count > 0) { ptd.SelectedTables = options.Tables; } } if (ptd.ShowModal() != true) { return; } var classBasis = string.Empty; if (dbInfo.DatabaseType == DatabaseType.Npgsql) { classBasis = EnvDteHelper.GetNpgsqlDatabaseName(dbInfo.ConnectionString); } else { classBasis = RepositoryHelper.GetClassBasis(dbInfo.ConnectionString, dbInfo.DatabaseType); } var model = revEng.GenerateClassName(classBasis) + "Context"; var packageResult = project.ContainsEfCoreReference(dbInfo.DatabaseType); var modelDialog = new EfCoreModelDialog(options) { 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 }; _package.Dte2.StatusBar.Text = "Getting options..."; if (modelDialog.ShowModal() != true) { return; } options = new ReverseEngineerOptions { UseFluentApiOnly = !modelDialog.UseDataAnnotations, ConnectionString = dbInfo.ConnectionString, ContextClassName = modelDialog.ModelName, DatabaseType = (ReverseEngineer20.DatabaseType)dbInfo.DatabaseType, ProjectPath = projectPath, OutputPath = modelDialog.OutputPath, ProjectRootNamespace = modelDialog.NameSpace, UseDatabaseNames = modelDialog.UseDatabaseNames, UseInflector = modelDialog.UsePluralizer, IdReplace = modelDialog.ReplaceId, UseHandleBars = modelDialog.UseHandelbars, IncludeConnectionString = modelDialog.IncludeConnectionString, SelectedToBeGenerated = modelDialog.SelectedTobeGenerated, Dacpac = dacpacPath, DefaultDacpacSchema = dacpacSchema, Tables = ptd.Tables }; _package.Dte2.StatusBar.Text = "Generating code..."; var tfm = project.Properties.Item("TargetFrameworkMoniker").Value.ToString(); bool isNetCore = tfm.Contains(".NETCoreApp,Version=v2.0"); bool isNetStandard = tfm.Contains(".NETStandard,Version=v2.0"); //TODO await update //if (modelDialog.UseHandelbars) //{ // var dropped = (DropTemplates(projectPath)); // if (dropped && !isNetCore && !isNetStandard) // { // project.ProjectItems.AddFromDirectory(Path.Combine(projectPath, "CodeTemplates")); // } //} var revEngResult = revEng.GenerateFiles(options); if (modelDialog.SelectedTobeGenerated == 0 || modelDialog.SelectedTobeGenerated == 2) { foreach (var filePath in revEngResult.EntityTypeFilePaths) { project.ProjectItems.AddFromFile(filePath); } if (modelDialog.SelectedTobeGenerated == 2) { if (File.Exists(revEngResult.ContextFilePath)) { File.Delete(revEngResult.ContextFilePath); } } } if (modelDialog.SelectedTobeGenerated == 0 || modelDialog.SelectedTobeGenerated == 1) { project.ProjectItems.AddFromFile(revEngResult.ContextFilePath); if (!isNetCore && !isNetStandard) { _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath); } if (modelDialog.SelectedTobeGenerated == 1) { foreach (var filePath in revEngResult.EntityTypeFilePaths) { if (File.Exists(filePath)) { File.Delete(filePath); } } } } var missingProviderPackage = packageResult.Item1 ? null : packageResult.Item2; if (modelDialog.InstallNuGetPackage) { missingProviderPackage = null; } _package.Dte2.StatusBar.Text = "Reporting result..."; var errors = ReportRevEngErrors(revEngResult, missingProviderPackage); SaveOptions(project, optionsPath, options); if (modelDialog.InstallNuGetPackage) { _package.Dte2.StatusBar.Text = "Installing EF Core provider package"; var nuGetHelper = new NuGetHelper(); await nuGetHelper.InstallPackageAsync(packageResult.Item2, project); } var duration = DateTime.Now - startTime; _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); } }