public static ReverseEngineerOptions TryRead(string optionsPath)
        {
            if (!File.Exists(optionsPath))
            {
                return(null);
            }
            if (File.Exists(optionsPath + ".ignore"))
            {
                return(null);
            }

            // Top-down deserialization:
            // Try to deserialize the current head version of the class.
            // If this fails, go top down with older versions and migrate them to the head version.

            var couldRead = TryRead(optionsPath, out ReverseEngineerOptions deserialized);

            if (couldRead)
            {
                return(deserialized);
            }

            couldRead = TryRead(optionsPath, out ReverseEngineerOptionsV1 deserializedV1);
            if (couldRead)
            {
                return(ReverseEngineerOptions.FromV1(deserializedV1));
            }

            // Fallback
            return(null);
        }
        public ReverseEngineerOptions TryReadOptions(string optionsPath)
        {
            if (!File.Exists(optionsPath))
            {
                return(null);
            }
            if (File.Exists(optionsPath + ".ignore"))
            {
                return(null);
            }

            ReverseEngineerOptions deserializedOptions = null;

            try
            {
                var ms  = new MemoryStream(Encoding.UTF8.GetBytes(File.ReadAllText(optionsPath, Encoding.UTF8)));
                var ser = new DataContractJsonSerializer(typeof(ReverseEngineerOptions));
                deserializedOptions = ser.ReadObject(ms) as ReverseEngineerOptions;
                ms.Close();
            }
            catch (Exception ex)
            {
                _package.LogError(new List <string> {
                    "Unable to load options"
                }, ex);
            }
            return(deserializedOptions);
        }
        private IReverseEngineerScaffolder CreateScaffolder(ReverseEngineerOptions options)
        {
            var fileService = new InMemoryTemplateFileService();

            fileService.InputFiles(ContextClassTemplate, ContextImportsTemplate,
                                   ContextCtorTemplate, ContextOnConfiguringTemplate, ContextDbSetsTemplate,
                                   EntityClassTemplate, EntityImportsTemplate, EntityCtorTemplate, EntityPropertiesTemplate);

            var services = new ServiceCollection()
                           .AddEntityFrameworkDesignTimeServices()
                           .AddSingleton <IDbContextTemplateService, FakeHbsDbContextTemplateService>()
                           .AddSingleton <IEntityTypeTemplateService, FakeHbsEntityTypeTemplateService>()
                           .AddSingleton <IEntityTypeTransformationService, HbsEntityTypeTransformationService>()
                           .AddSingleton <ITypeScriptHelper, TypeScriptHelper>()
                           .AddSingleton <ITemplateFileService>(fileService)
                           .AddSingleton <ITemplateLanguageService, FakeTypeScriptTemplateLanguageService>()
                           .AddSingleton <IModelCodeGenerator, HbsTypeScriptModelGenerator>()
                           .AddSingleton(provider =>
            {
                ICSharpDbContextGenerator contextGenerator = new HbsCSharpDbContextGenerator(
                    provider.GetRequiredService <IProviderConfigurationCodeGenerator>(),
                    provider.GetRequiredService <IAnnotationCodeGenerator>(),
                    provider.GetRequiredService <IDbContextTemplateService>(),
                    provider.GetRequiredService <IEntityTypeTransformationService>(),
                    provider.GetRequiredService <ICSharpHelper>(),
                    provider.GetRequiredService <IOptions <HandlebarsScaffoldingOptions> >());
                return(options == ReverseEngineerOptions.DbContextOnly ||
                       options == ReverseEngineerOptions.DbContextAndEntities
                        ? contextGenerator
                        : new NullCSharpDbContextGenerator());
            })
                           .AddSingleton(provider =>
            {
                ICSharpEntityTypeGenerator entityGenerator = new HbsTypeScriptEntityTypeGenerator(
                    provider.GetRequiredService <IEntityTypeTemplateService>(),
                    provider.GetRequiredService <IEntityTypeTransformationService>(),
                    provider.GetRequiredService <ICSharpHelper>(),
                    provider.GetRequiredService <ITypeScriptHelper>(),
                    provider.GetRequiredService <IOptions <HandlebarsScaffoldingOptions> >());
                return(options == ReverseEngineerOptions.EntitiesOnly ||
                       options == ReverseEngineerOptions.DbContextAndEntities
                        ? entityGenerator
                        : new NullCSharpEntityTypeGenerator());
            })
                           .AddSingleton <IHbsHelperService>(provider =>
                                                             new HbsHelperService(new Dictionary <string, Action <TextWriter, Dictionary <string, object>, object[]> >
            {
                { EntityFrameworkCore.Scaffolding.Handlebars.Helpers.Constants.SpacesHelper, HandlebarsHelpers.SpacesHelper }
            }))
                           .AddSingleton <IHbsBlockHelperService>(provider =>
                                                                  new HbsBlockHelperService(new Dictionary <string, Action <TextWriter, HelperOptions, Dictionary <string, object>, object[]> >()))
                           .AddSingleton <IReverseEngineerScaffolder, HbsReverseEngineerScaffolder>();

            new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services);
            var scaffolder = services
                             .BuildServiceProvider()
                             .GetRequiredService <IReverseEngineerScaffolder>();

            return(scaffolder);
        }
Beispiel #4
0
        public static ReverseEngineerResult LaunchExternalRunner(ReverseEngineerOptions options, bool useEFCore5)
        {
            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,
                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,
            };

            var launcher = new EfRevEngLauncher(commandOptions, useEFCore5);

            return(launcher.GetOutput());
        }
Beispiel #5
0
 private void SaveOptions(Project project, string optionsPath, ReverseEngineerOptions options)
 {
     if (!File.Exists(optionsPath + ".ignore"))
     {
         File.WriteAllText(optionsPath, options.Write(), Encoding.UTF8);
         project.ProjectItems.AddFromFile(optionsPath);
     }
 }
        public string WriteOptions(ReverseEngineerOptions options)
        {
            var ms  = new MemoryStream();
            var ser = new DataContractJsonSerializer(typeof(ReverseEngineerOptions));

            ser.WriteObject(ms, options);
            byte[] json = ms.ToArray();
            ms.Close();
            return(Encoding.UTF8.GetString(json, 0, json.Length));
        }
 /// <summary>
 ///     <para>
 ///         Registers the Handlebars scaffolding generator as a service in the <see cref="IServiceCollection" />.
 ///         This allows you to customize generated DbContext and entity type classes by modifying the Handlebars
 ///         templates in the CodeTemplates folder.
 ///     </para>
 ///     <para>
 ///         Has <paramref name="options" /> that allow you to choose whether to generate only the DbContext class,
 ///         only entity type classes, or both DbContext and entity type classes (the default).
 ///     </para>
 /// </summary>
 /// <param name="services"> The <see cref="IServiceCollection" /> to add services to. </param>
 /// <param name="options">Options for reverse engineering classes from an existing database.</param>
 /// <param name="language">Language option.</param>
 /// <returns>The same service collection so that multiple calls can be chained.</returns>
 public static IServiceCollection AddHandlebarsScaffolding(this IServiceCollection services,
                                                           ReverseEngineerOptions options = ReverseEngineerOptions.DbContextAndEntities,
                                                           LanguageOptions language       = LanguageOptions.CSharp)
 {
     return(services.AddHandlebarsScaffolding(scaffoldingOptions =>
     {
         scaffoldingOptions.ReverseEngineerOptions = options;
         scaffoldingOptions.LanguageOptions = language;
     }));
 }
        private void SaveOptions(Project project, string optionsPath, ReverseEngineerOptions options, Tuple <List <Schema>, string> renamingOptions)
        {
            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"))
            {
                File.WriteAllText(renamingOptions.Item2, CustomNameOptionsExtensions.Write(renamingOptions.Item1), Encoding.UTF8);
                project.ProjectItems.AddFromFile(renamingOptions.Item2);
            }
        }
        public static string Write(this ReverseEngineerOptions options)
        {
            using (var ms = new MemoryStream())
            {
                using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8, true, true, "   "))
                {
                    var serializer = new DataContractJsonSerializer(typeof(ReverseEngineerOptions));
                    serializer.WriteObject(writer, options);
                    writer.Flush();
                }

                var json = ms.ToArray();
                return(Encoding.UTF8.GetString(json, 0, json.Length));
            }
        }
        /// <summary>
        ///     <para>
        ///         Registers the Handlebars scaffolding generator as a service in the <see cref="IServiceCollection" />.
        ///         This allows you to customize generated DbContext and entity type classes by modifying the Handlebars
        ///         templates in the CodeTemplates folder.
        ///     </para>
        ///     <para>
        ///         Has <paramref name="options" /> that allow you to choose whether to generate only the DbContext class,
        ///         only entity type classes, or both DbContext and entity type classes (the default).
        ///         This can be useful when placing model classes in a separate class library.
        ///     </para>
        /// </summary>
        /// <param name="services"> The <see cref="IServiceCollection" /> to add services to. </param>
        /// <param name="options">Options for reverse engineering classes from an existing database.</param>
        /// <returns>The same service collection so that multiple calls can be chained.</returns>
        public static IServiceCollection AddHandlebarsScaffolding(this IServiceCollection services,
                                                                  ReverseEngineerOptions options = ReverseEngineerOptions.DbContextAndEntities)
        {
            Type dbContextGeneratorImpl;
            var  dbContextGeneratorType = typeof(ICSharpDbContextGenerator);

            if (options == ReverseEngineerOptions.DbContextOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                dbContextGeneratorImpl = typeof(HbsCSharpDbContextGenerator);
            }
            else
            {
                dbContextGeneratorImpl = typeof(NullCSharpDbContextGenerator);
            }
            services.AddSingleton(dbContextGeneratorType, dbContextGeneratorImpl);

            Type entityGeneratorImpl;
            var  entityGeneratorType = typeof(ICSharpEntityTypeGenerator);

            if (options == ReverseEngineerOptions.EntitiesOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                entityGeneratorImpl = typeof(HbsCSharpEntityTypeGenerator);
            }
            else
            {
                entityGeneratorImpl = typeof(NullCSharpEntityTypeGenerator);
            }
            services.AddSingleton(entityGeneratorType, entityGeneratorImpl);

            services.AddSingleton <ITemplateFileService, FileSystemTemplateFileService>();
            services.AddSingleton <IDbContextTemplateService, HbsDbContextTemplateService>();
            services.AddSingleton <IEntityTypeTemplateService, HbsEntityTypeTemplateService>();
            services.AddSingleton <IModelCodeGenerator, HbsCSharpModelGenerator>();
            services.AddSingleton <IReverseEngineerScaffolder, HbsReverseEngineerScaffolder>();
            services.AddSingleton <IEntityTypeTransformationService, HbsEntityTypeTransformationService>();
            services.AddSingleton <IHbsHelperService, HbsHelperService>(provider =>
            {
                var helpers = new Dictionary <string, Action <TextWriter, Dictionary <string, object>, object[]> >
                {
                    { Constants.SpacesHelper, HandlebarsHelpers.SpacesHelper }
                };
                return(new HbsHelperService(helpers));
            });
            return(services);
        }
        private Dictionary <string, string> GetGeneratedFiles(ScaffoldedModel model, ReverseEngineerOptions options)
        {
            var generatedFiles = new Dictionary <string, string>();

            if (options == ReverseEngineerOptions.DbContextOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                generatedFiles.Add(Constants.Files.TypeScriptFiles.DbContextFile, model.ContextFile.Code);
            }

            if (options == ReverseEngineerOptions.EntitiesOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                generatedFiles.Add(Constants.Files.TypeScriptFiles.CategoryFile, model.AdditionalFiles[0].Code);
                generatedFiles.Add(Constants.Files.TypeScriptFiles.ProductFile, model.AdditionalFiles[1].Code);
            }

            return(generatedFiles);
        }
Beispiel #12
0
        public static string Write(this ReverseEngineerOptions options, string projectDirectory)
        {
            if (!string.IsNullOrEmpty(options.UiHint))
            {
                options.UiHint = SetRelativePathForSqlProj(options.UiHint, projectDirectory);
            }

            using (var ms = new MemoryStream())
            {
                using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8, true, true, "   "))
                {
                    var serializer = new DataContractJsonSerializer(typeof(ReverseEngineerOptions));
                    serializer.WriteObject(writer, options);
                    writer.Flush();
                }

                var json = ms.ToArray();
                return(Encoding.UTF8.GetString(json, 0, json.Length));
            }
        }
Beispiel #13
0
 public EfCoreModelDialog(ReverseEngineerOptions options)
 {
     _options = options;
     Telemetry.TrackPageView(nameof(EfCoreModelDialog));
     InitializeComponent();
     Background = VsThemes.GetWindowBackground();
     if (_options != null)
     {
         chkDataAnnoations.IsChecked          = !options.UseFluentApiOnly;
         chkUseDatabaseNames.IsChecked        = options.UseDatabaseNames;
         chkPluralize.IsChecked               = options.UseInflector;
         chkHandlebars.IsChecked              = options.UseHandleBars;
         chkIdReplace.IsChecked               = options.IdReplace;
         chkIncludeConnectionString.IsChecked = options.IncludeConnectionString;
         ModelName  = options.ContextClassName;
         NameSpace  = options.ProjectRootNamespace;
         OutputPath = options.OutputPath;
         cmbLanguage.SelectedIndex = options.SelectedToBeGenerated;
         SetCheckState();
     }
 }
Beispiel #14
0
        public static ReverseEngineerOptions TryRead(string optionsPath)
        {
            if (!File.Exists(optionsPath))
            {
                return(null);
            }
            if (File.Exists(optionsPath + ".ignore"))
            {
                return(null);
            }

            ReverseEngineerOptions deserializedOptions = null;

            try
            {
                var ms  = new MemoryStream(Encoding.UTF8.GetBytes(File.ReadAllText(optionsPath, Encoding.UTF8)));
                var ser = new DataContractJsonSerializer(typeof(ReverseEngineerOptions));
                deserializedOptions = ser.ReadObject(ms) as ReverseEngineerOptions;
                ms.Close();
            }
            catch { }
            return(deserializedOptions);
        }
Beispiel #15
0
        /// <summary>
        ///     <para>
        ///         Registers the Handlebars scaffolding generator as a service in the <see cref="IServiceCollection" />.
        ///         This allows you to customize generated DbContext and entity type classes by modifying the Handlebars
        ///         templates in the CodeTemplates folder.
        ///     </para>
        ///     <para>
        ///         Has <paramref name="options" /> that allow you to choose whether to generate only the DbContext class,
        ///         only entity type classes, or both DbContext and entity type classes (the default).
        ///         This can be useful when placing model classes in a separate class library.
        ///     </para>
        /// </summary>
        /// <param name="services"> The <see cref="IServiceCollection" /> to add services to. </param>
        /// <param name="options">Options for reverse engineering classes from an existing database.</param>
        /// <returns>The same service collection so that multiple calls can be chained.</returns>
        public static IServiceCollection AddHandlebarsScaffolding(this IServiceCollection services,
                                                                  ReverseEngineerOptions options = ReverseEngineerOptions.DbContextAndEntities)
        {
            Type dbContextGeneratorImpl;
            var  dbContextGeneratorType = typeof(ICSharpDbContextGenerator);

            if (options == ReverseEngineerOptions.DbContextOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                dbContextGeneratorImpl = typeof(HbsCSharpDbContextGenerator);
            }
            else
            {
                dbContextGeneratorImpl = typeof(NullCSharpDbContextGenerator);
            }
            services.AddSingleton(dbContextGeneratorType, dbContextGeneratorImpl);

            Type entityGeneratorImpl;
            var  entityGeneratorType = typeof(ICSharpEntityTypeGenerator);

            if (options == ReverseEngineerOptions.EntitiesOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                entityGeneratorImpl = typeof(HbsCSharpEntityTypeGenerator);
            }
            else
            {
                entityGeneratorImpl = typeof(NullCSharpEntityTypeGenerator);
            }
            services.AddSingleton(entityGeneratorType, entityGeneratorImpl);

            services.AddSingleton <ITemplateFileService, FileSystemTemplateFileService>();
            services.AddSingleton <IDbContextTemplateService, HbsDbContextTemplateService>();
            services.AddSingleton <IEntityTypeTemplateService, HbsEntityTypeTemplateService>();
            services.AddSingleton <IScaffoldingCodeGenerator, HbsCSharpScaffoldingGenerator>();
            return(services);
        }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
 public string GetReadMeText(ReverseEngineerOptions options, string content)
 {
     return(content.Replace("[ProviderName]", GetProviderName(options.DatabaseType))
            .Replace("[ConnectionString]", options.ConnectionString)
            .Replace("[ContextName]", options.ContextClassName));
 }
Beispiel #19
0
 private IReverseEngineerScaffolder CreateScaffolder(ReverseEngineerOptions revEngOptions, string filenamePrefix = null)
 {
     return(CreateScaffolder(revEngOptions, _ => { }, filenamePrefix));
 }
Beispiel #20
0
        private IReverseEngineerScaffolder CreateScaffolder(ReverseEngineerOptions revEngOptions, Action <HandlebarsScaffoldingOptions> configureOptions, string filenamePrefix = null)
        {
            var fileService = new InMemoryTemplateFileService();

            fileService.InputFiles(ContextClassTemplate, ContextImportsTemplate,
                                   ContextCtorTemplate, ContextOnConfiguringTemplate, ContextDbSetsTemplate,
                                   EntityClassTemplate, EntityImportsTemplate, EntityCtorTemplate, EntityPropertiesTemplate);

            var services = new ServiceCollection()
                           .AddEntityFrameworkDesignTimeServices()
                           .AddSingleton <IDbContextTemplateService, FakeHbsDbContextTemplateService>()
                           .AddSingleton <IEntityTypeTemplateService, FakeHbsEntityTypeTemplateService>()
                           .AddSingleton <ITemplateFileService>(fileService)
                           .AddSingleton <ITemplateLanguageService, FakeCSharpTemplateLanguageService>()
                           .AddSingleton <IModelCodeGenerator, HbsCSharpModelGenerator>();

#pragma warning disable EF1001 // Internal EF Core API usage.
            services
            .AddSingleton(provider =>
            {
                ICSharpDbContextGenerator contextGenerator = new HbsCSharpDbContextGenerator(
                    provider.GetRequiredService <IProviderConfigurationCodeGenerator>(),
                    provider.GetRequiredService <IAnnotationCodeGenerator>(),
                    provider.GetRequiredService <IDbContextTemplateService>(),
                    provider.GetRequiredService <IEntityTypeTransformationService>(),
                    provider.GetRequiredService <ICSharpHelper>(),
                    provider.GetRequiredService <IOptions <HandlebarsScaffoldingOptions> >());
                return(revEngOptions == ReverseEngineerOptions.DbContextOnly ||
                       revEngOptions == ReverseEngineerOptions.DbContextAndEntities
                        ? contextGenerator
                        : new NullCSharpDbContextGenerator());
            })
            .AddSingleton(provider =>
            {
                ICSharpEntityTypeGenerator entityGenerator = new HbsCSharpEntityTypeGenerator(
                    provider.GetRequiredService <IAnnotationCodeGenerator>(),
                    provider.GetRequiredService <ICSharpHelper>(),
                    provider.GetRequiredService <IEntityTypeTemplateService>(),
                    provider.GetRequiredService <IEntityTypeTransformationService>(),
                    provider.GetRequiredService <IOptions <HandlebarsScaffoldingOptions> >());
                return(revEngOptions == ReverseEngineerOptions.EntitiesOnly ||
                       revEngOptions == ReverseEngineerOptions.DbContextAndEntities
                        ? entityGenerator
                        : new NullCSharpEntityTypeGenerator());
            });
#pragma warning restore EF1001 // Internal EF Core API usage.

            services
            .AddSingleton <IHbsHelperService>(provider =>
                                              new HbsHelperService(new Dictionary <string, Action <TextWriter, Dictionary <string, object>, object[]> >
            {
                { EntityFrameworkCore.Scaffolding.Handlebars.Helpers.Constants.SpacesHelper, HandlebarsHelpers.SpacesHelper }
            }))
            .AddSingleton <IHbsBlockHelperService>(provider =>
                                                   new HbsBlockHelperService(new Dictionary <string, Action <TextWriter, HelperOptions, Dictionary <string, object>, object[]> >()))
            .AddSingleton <IReverseEngineerScaffolder, HbsReverseEngineerScaffolder>();


            if (string.IsNullOrWhiteSpace(filenamePrefix))
            {
                services
                .AddSingleton <IContextTransformationService, HbsContextTransformationService>()
                .AddSingleton <IEntityTypeTransformationService, HbsEntityTypeTransformationService>();
            }
            else
            {
                services
                .AddSingleton <IContextTransformationService>(y => new HbsContextTransformationService(contextName => $"{filenamePrefix}{contextName}"))
                .AddSingleton <IEntityTypeTransformationService>(y => new HbsEntityTypeTransformationService(entityFileNameTransformer: entityName => $"{filenamePrefix}{entityName}"));
            }

            services.Configure(configureOptions);

#pragma warning disable EF1001 // Internal EF Core API usage.
            new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services);
#pragma warning restore EF1001 // Internal EF Core API usage.
            var scaffolder = services
                             .BuildServiceProvider()
                             .GetRequiredService <IReverseEngineerScaffolder>();
            return(scaffolder);
        }
        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);
            }
        }
Beispiel #22
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
            {
                if (_package.Dte2.Mode == vsIDEMode.vsIDEModeDebug)
                {
                    EnvDteHelper.ShowError("Cannot generate code while debugging");
                    return;
                }

                var startTime = DateTime.Now;

                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 ptd = new PickTablesDialog {
                    IncludeTables = true
                };
                using (var repository = RepositoryHelper.CreateRepository(dbInfo))
                {
                    ptd.Tables = repository.GetAllTableNamesForExclusion();
                }

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

                var classBasis = RepositoryHelper.GetClassBasis(dbInfo.ConnectionString, dbInfo.DatabaseType);

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

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

                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     = 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,
                    Tables = ptd.Tables
                };

                _package.Dte2.StatusBar.Text = "Generating code...";

                if (modelDialog.UseHandelbars)
                {
                    if (DropTemplates(projectPath))
                    {
                        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 == 0 || modelDialog.SelectedTobeGenerated == 1)
                {
                    project.ProjectItems.AddFromFile(revEngResult.ContextFilePath);
                    _package.Dte2.ItemOperations.OpenFile(revEngResult.ContextFilePath);
                }

                packageResult = dteH.ContainsEfCoreReference(project, dbInfo.DatabaseType);

                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();
                    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);
            }
        }
Beispiel #24
0
        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,
                    }));

                    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 && options.FilterSchemas && options.Schemas != null && options.Schemas.Any())
                {
                    psd.PublishSchemas(options.Schemas);
                }

                if (options != null)
                {
                    psd.PublishCodeGenerationMode(options.CodeGenerationMode);
                }

                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...";

                // Reload the database list, in case the user has added a new database in the dialog
                databaseList = VsDataHelper.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.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;
                }

                //TODO Enable when Oracle EF Core 5 provider is released
                if (useEFCore5 && (dbInfo.DatabaseType == DatabaseType.Oracle))
                {
                    EnvDteHelper.ShowError($"Unsupported provider with EF Core 5.0: {dbInfo.DatabaseType}");
                    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,
                };

                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.");
                    }
                }

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

                if (modelingOptionsResult.Payload.UseHandlebars)
                {
                    var dropped = (DropTemplates(projectPath, useEFCore5));
                    if (dropped && !project.IsNetCore() && !isNetStandard)
                    {
                        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)
                    {
                        if (!project.IsNetCore() && !isNetStandard)
                        {
                            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)
                {
                    if (!project.IsNetCore() && !isNetStandard)
                    {
                        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);
            }
        }
        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);
            }
        }
        private Dictionary <string, string> ReverseEngineerFiles(ReverseEngineerOptions options, bool useDataAnnotations)
        {
            var fileService = new InMemoryTemplateFileService();

            fileService.InputFiles(ContextClassTemplate, ContextImportsTemplate, ContextDbSetsTemplate,
                                   EntityClassTemplate, EntityImportsTemplate, EntityCtorTemplate, EntityPropertiesTemplate);
            var dbContextTemplateService  = new HbsDbContextTemplateService(fileService);
            var entityTypeTemplateService = new HbsEntityTypeTemplateService(fileService);

            ICSharpUtilities          cSharpUtilities      = new CSharpUtilities();
            ICSharpDbContextGenerator realContextGenerator = new HbsCSharpDbContextGenerator(
                new SqlServerScaffoldingCodeGenerator(),
                new SqlServerAnnotationCodeGenerator(new AnnotationCodeGeneratorDependencies()),
                cSharpUtilities,
                new HbsDbContextTemplateService(fileService));
            ICSharpDbContextGenerator contextGenerator =
                options == ReverseEngineerOptions.DbContextOnly || options == ReverseEngineerOptions.DbContextOnly
                ? realContextGenerator
                : new NullCSharpDbContextGenerator();
            ICSharpEntityTypeGenerator realEntityGenerator = new HbsCSharpEntityTypeGenerator(
                cSharpUtilities,
                new HbsEntityTypeTemplateService(fileService));
            ICSharpEntityTypeGenerator entityGenerator =
                options == ReverseEngineerOptions.EntitiesOnly || options == ReverseEngineerOptions.DbContextAndEntities
                ? realEntityGenerator
                : new NullCSharpEntityTypeGenerator();
            IScaffoldingCodeGenerator scaffoldingGenerator = new HbsCSharpScaffoldingGenerator(
                fileService, dbContextTemplateService, entityTypeTemplateService,
                contextGenerator, entityGenerator);

            var modelFactory = new SqlServerDatabaseModelFactory(
                new DiagnosticsLogger <DbLoggerCategory.Scaffolding>(
                    new TestSqlLoggerFactory(),
                    new LoggingOptions(),
                    new DiagnosticListener("Fake")));
            var reverseEngineer = new ReverseEngineerScaffolder(
                modelFactory,
                new FakeScaffoldingModelFactory(new TestOperationReporter()),
                scaffoldingGenerator, cSharpUtilities);

            // Act
            var files = reverseEngineer.Generate(
                connectionString: Constants.Connections.SqlServerConnection,
                tables: Enumerable.Empty <string>(),
                schemas: Enumerable.Empty <string>(),
                projectPath: Constants.Parameters.ProjectPath,
                outputPath: null,
                rootNamespace: Constants.Parameters.RootNamespace,
                contextName: Constants.Parameters.ContextName,
                useDataAnnotations: useDataAnnotations,
                overwriteFiles: false,
                useDatabaseNames: false);

            var generatedFiles = new Dictionary <string, string>();

            if (options == ReverseEngineerOptions.DbContextOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                var contextPath = files.ContextFile;
                var context     = fileService.RetrieveTemplateFileContents(
                    Path.GetDirectoryName(contextPath), Path.GetFileName(contextPath));
                generatedFiles.Add(Constants.Files.DbContextFile, context);
            }

            if (options == ReverseEngineerOptions.EntitiesOnly ||
                options == ReverseEngineerOptions.DbContextAndEntities)
            {
                var categoryPath = files.EntityTypeFiles[0];
                var category     = fileService.RetrieveTemplateFileContents(
                    Path.GetDirectoryName(categoryPath), Path.GetFileName(categoryPath));
                var productPath = files.EntityTypeFiles[1];
                var product     = fileService.RetrieveTemplateFileContents(
                    Path.GetDirectoryName(productPath), Path.GetFileName(productPath));
                generatedFiles.Add(Constants.Files.CategoryFile, category);
                generatedFiles.Add(Constants.Files.ProductFile, product);
            }

            return(generatedFiles);
        }