public async void GenerateEfCoreModelInProject(object sender, ExecutedRoutedEventArgs e)
        {
            var databaseInfo = ValidateMenuInfo(sender);

            if (databaseInfo == null)
            {
                return;
            }

            var dbType = databaseInfo.DatabaseInfo.DatabaseType;

            var dte = package?.GetServiceHelper(typeof(DTE)) as DTE;

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

            var dteH    = new EnvDteHelper();
            var project = dteH.GetProject(dte);

            if (project == null)
            {
                EnvDteHelper.ShowError("Please select a project in Solution Explorer, where you want the EF Core Model to be placed");
                return;
            }

            try
            {
                var ptd = new PickTablesDialog {
                    IncludeTables = true
                };
                using (var repository = Helpers.RepositoryHelper.CreateRepository(new DatabaseInfo {
                    ConnectionString = databaseInfo.DatabaseInfo.ConnectionString, DatabaseType = databaseInfo.DatabaseInfo.DatabaseType
                }))
                {
                    ptd.Tables = repository.GetAllTableNamesForExclusion();
                }

                var res = ptd.ShowModal();
                if (!res.HasValue || !res.Value)
                {
                    return;
                }

                var revEng = new EfCoreReverseEngineer();

                var classBasis = Helpers.RepositoryHelper.GetClassBasis(databaseInfo.DatabaseInfo.ConnectionString, dbType);

                var model         = revEng.GenerateClassName(classBasis) + "Context";
                var packageResult = dteH.ContainsEfCoreReference(project, dbType);

                var modelDialog = new EfCoreModelDialog
                {
                    InstallNuGetPackage = !packageResult.Item1,
                    ModelName           = model,
                    ProjectName         = project.Name,
                    NameSpace           = project.Properties.Item("DefaultNamespace").Value.ToString()
                };
                var result = modelDialog.ShowModal();
                if (!result.HasValue || result.Value != true)
                {
                    return;
                }

                var projectPath = project.Properties.Item("FullPath").Value.ToString();

                var options = new ReverseEngineerOptions
                {
                    UseFluentApiOnly     = !modelDialog.UseDataAnnotations,
                    ConnectionString     = databaseInfo.DatabaseInfo.ConnectionString,
                    ContextClassName     = modelDialog.ModelName,
                    DatabaseType         = (EFCoreReverseEngineer.DatabaseType)dbType,
                    ProjectPath          = projectPath,
                    OutputPath           = modelDialog.OutputPath,
                    ProjectRootNamespace = modelDialog.NameSpace,
                    Tables = ptd.Tables
                };

                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 == 0 || modelDialog.SelectedTobeGenerated == 1)
                {
                    project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);
                    dte.ItemOperations.OpenFile(revEngResult.ContextFilePath);
                }

                packageResult = dteH.ContainsEfCoreReference(project, dbType);

                var missingProviderPackage = packageResult.Item1 ? null : packageResult.Item2;
                if (modelDialog.InstallNuGetPackage)
                {
                    missingProviderPackage = null;
                }

                ReportRevEngErrors(revEngResult, missingProviderPackage);

                if (modelDialog.InstallNuGetPackage)
                {
                    package.SetStatus("Installing EF Core provider package");
                    var nuGetHelper = new NuGetHelper();
                    await nuGetHelper.InstallPackageAsync(packageResult.Item2, project);
                }

                DataConnectionHelper.LogUsage("DatabaseCreateEfCoreModel");
            }
            catch (Exception ex)
            {
                package.SetStatus(null);
                DataConnectionHelper.SendError(ex, databaseInfo.DatabaseInfo.DatabaseType, false);
            }
        }
Example #2
0
        public void GenerateEfCoreModelInProject(object sender, ExecutedRoutedEventArgs e)
        {
            var databaseInfo = ValidateMenuInfo(sender);

            if (databaseInfo == null)
            {
                return;
            }

            var dbType = databaseInfo.DatabaseInfo.DatabaseType;

            var dte = package?.GetServiceHelper(typeof(DTE)) as DTE;

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

            var dteH    = new EnvDteHelper();
            var project = dteH.GetProject(dte);

            if (project == null)
            {
                EnvDteHelper.ShowError("Please select a project in Solution Explorer, where you want the EF Core Model to be placed");
                return;
            }

            try
            {
                var ptd = new PickTablesDialog {
                    IncludeTables = true
                };
                using (var repository = DataConnectionHelper.CreateRepository(new DatabaseInfo {
                    ConnectionString = databaseInfo.DatabaseInfo.ConnectionString, DatabaseType = databaseInfo.DatabaseInfo.DatabaseType
                }))
                {
                    ptd.Tables = repository.GetAllTableNamesForExclusion();
                }
                var res = ptd.ShowModal();
                if (!res.HasValue || !res.Value)
                {
                    return;
                }

                var revEng = new EFCoreReverseEngineer.EfCoreReverseEngineer();

                var classBasis = Path.GetFileNameWithoutExtension(databaseInfo.DatabaseInfo.Caption);
                if (dbType == DatabaseType.SQLServer)
                {
                    classBasis = new SqlConnectionStringBuilder(databaseInfo.DatabaseInfo.ConnectionString).InitialCatalog;
                }

                var model = revEng.GenerateClassName(classBasis) + "Context";

                var modelDialog = new EfCoreModelDialog
                {
                    ModelName   = model,
                    ProjectName = project.Name,
                    NameSpace   = project.Properties.Item("DefaultNamespace").Value.ToString()
                };
                var result = modelDialog.ShowModal();
                if (!result.HasValue || result.Value != true)
                {
                    return;
                }

                var projectPath = project.Properties.Item("FullPath").Value.ToString();

                var options = new ReverseEngineerOptions
                {
                    UseFluentApiOnly     = !modelDialog.UseDataAnnotations,
                    ConnectionString     = databaseInfo.DatabaseInfo.ConnectionString,
                    ContextClassName     = modelDialog.ModelName,
                    DatabaseType         = (EFCoreReverseEngineer.DatabaseType)dbType,
                    ProjectPath          = projectPath,
                    OutputPath           = modelDialog.OutputPath,
                    ProjectRootNamespace = modelDialog.NameSpace,
                    Tables = ptd.Tables
                };

                var revEngResult = revEng.GenerateFiles(options);

                foreach (var filePath in revEngResult.FilePaths)
                {
                    project.ProjectItems.AddFromFile(filePath);
                }
                if (revEngResult.FilePaths.Count > 0)
                {
                    dte.ItemOperations.OpenFile(revEngResult.FilePaths.Last());
                }

                ReportRevEngErrors(revEngResult, dteH.ContainsEfCoreReference(project, dbType));

                DataConnectionHelper.LogUsage("DatabaseCreateEfCoreModel");
            }
            catch (Exception ex)
            {
                DataConnectionHelper.SendError(ex, databaseInfo.DatabaseInfo.DatabaseType, false);
            }
        }
        public async void ReverseEngineerCodeFirst(Project project)
        {
            try
            {
                var dteH   = new EnvDteHelper();
                var revEng = new EfCoreReverseEngineer();

                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 psd     = new PickServerDatabaseDialog(databaseList, _package);
                var diagRes = psd.ShowModal();
                if (!diagRes.HasValue || !diagRes.Value)
                {
                    return;
                }

                // Show dialog with SqlClient selected by default
                _package.Dte2.StatusBar.Text = "Loading schema information...";

                var dbInfo = psd.SelectedDatabase.Value;

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

                var options = TryReadOptions(optionsPath);

                var ptd = new PickTablesDialog {
                    IncludeTables = true
                };
                using (var repository = RepositoryHelper.CreateRepository(dbInfo))
                {
                    ptd.Tables = repository.GetAllTableNamesForExclusion();
                }

                if (options != null && options.Tables.Count > 0)
                {
                    ptd.SelectedTables = options.Tables;
                }

                var res = ptd.ShowModal();
                if (!res.HasValue || !res.Value)
                {
                    return;
                }

                var classBasis    = RepositoryHelper.GetClassBasis(dbInfo.ConnectionString, dbInfo.DatabaseType);
                var model         = revEng.GenerateClassName(classBasis) + "Context";
                var packageResult = dteH.ContainsEfCoreReference(project, 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()
                };

                _package.Dte2.StatusBar.Text = "Getting options...";
                var result = modelDialog.ShowModal();
                if (!result.HasValue || result.Value != 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,
                    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");

                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);
            }
        }
        public void ReverseEngineerCodeFirst(Project project)
        {
            try
            {
                if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug)
                {
                    EnvDteHelper.ShowError("Cannot generate code while debugging");
                    return;
                }

                var startTime = DateTime.Now;

                // Show dialog with SqlClient selected by default
                var dialogFactory = _package.GetService <IVsDataConnectionDialogFactory>();
                var dialog        = dialogFactory.CreateConnectionDialog();
                dialog.AddAllSources();
                dialog.SelectedSource = new Guid("067ea0d9-ba62-43f7-9106-34930c60c528");
                var dialogResult = dialog.ShowDialog(connect: true);

                if (dialogResult != null)
                {
                    _package.Dte2.StatusBar.Text = "Loading schema information...";

                    // Find connection string and provider
                    var             connection       = (DbConnection)dialogResult.GetLockedProviderObject();
                    var             connectionString = connection.ConnectionString;
                    var             providerManager  = (IVsDataProviderManager)Package.GetGlobalService(typeof(IVsDataProviderManager));
                    IVsDataProvider dp;
                    providerManager.Providers.TryGetValue(dialogResult.Provider, out dp);
                    var providerInvariant = (string)dp.GetProperty("InvariantName");

                    var dbType = DatabaseType.SQLCE35;
                    if (providerInvariant == "System.Data.SqlServerCe.4.0")
                    {
                        dbType = DatabaseType.SQLCE40;
                    }
                    if (providerInvariant == "System.Data.SQLite.EF6")
                    {
                        dbType = DatabaseType.SQLite;
                    }
                    if (providerInvariant == "System.Data.SqlClient")
                    {
                        dbType = DatabaseType.SQLServer;
                    }

                    if (dbType == DatabaseType.SQLCE35)
                    {
                        EnvDteHelper.ShowError($"Unsupported provider: {providerInvariant}");
                        return;
                    }

                    var ptd = new PickTablesDialog {
                        IncludeTables = true
                    };
                    using (var repository = RepositoryHelper.CreateRepository(new DatabaseInfo {
                        ConnectionString = connectionString, DatabaseType = dbType
                    }))
                    {
                        ptd.Tables = repository.GetAllTableNamesForExclusion();
                    }

                    var res = ptd.ShowModal();
                    if (!res.HasValue || !res.Value)
                    {
                        return;
                    }

                    var classBasis = RepositoryHelper.GetClassBasis(connectionString, dbType);

                    var dteH   = new EnvDteHelper();
                    var revEng = new EfCoreReverseEngineer();

                    var model         = revEng.GenerateClassName(classBasis) + "Context";
                    var packageResult = dteH.ContainsEfCoreReference(project, dbType);

                    var modelDialog = new EfCoreModelDialog
                    {
                        InstallNuGetPackage = !packageResult.Item1,
                        ModelName           = model,
                        ProjectName         = project.Name,
                        NameSpace           = project.Properties.Item("DefaultNamespace").Value.ToString()
                    };

                    _package.Dte2.StatusBar.Text = "Getting options...";
                    var result = modelDialog.ShowModal();
                    if (!result.HasValue || result.Value != true)
                    {
                        return;
                    }

                    var projectPath = project.Properties.Item("FullPath").Value.ToString();

                    var options = new ReverseEngineerOptions
                    {
                        UseFluentApiOnly     = !modelDialog.UseDataAnnotations,
                        ConnectionString     = connectionString,
                        ContextClassName     = modelDialog.ModelName,
                        DatabaseType         = (EFCoreReverseEngineer.DatabaseType)dbType,
                        ProjectPath          = projectPath,
                        OutputPath           = modelDialog.OutputPath,
                        ProjectRootNamespace = modelDialog.NameSpace,
                        UseDatabaseNames     = modelDialog.UseDatabaseNames,
                        Tables = ptd.Tables
                    };

                    _package.Dte2.StatusBar.Text = "Generating code...";
                    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 == 0 || modelDialog.SelectedTobeGenerated == 1)
                    {
                        project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);
                        _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath);
                    }

                    packageResult = dteH.ContainsEfCoreReference(project, dbType);

                    var missingProviderPackage = packageResult.Item1 ? null : packageResult.Item2;
                    if (modelDialog.InstallNuGetPackage)
                    {
                        missingProviderPackage = null;
                    }

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

                    if (modelDialog.InstallNuGetPackage)
                    {
                        _package.Dte2.StatusBar.Text = "Installing EF Core provider package";
                        var nuGetHelper = new NuGetHelper();
                        nuGetHelper.InstallPackage(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);
                    }
                }
            }
            catch (Exception exception)
            {
                _package.LogError(new List <string>(), exception);
            }
        }