Example #1
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual ScaffoldedModel ScaffoldModel(
            string connectionString,
            DatabaseModelFactoryOptions databaseOptions,
            ModelReverseEngineerOptions modelOptions,
            ModelCodeGenerationOptions codeOptions)
        {
            if (!string.IsNullOrWhiteSpace(codeOptions.ContextName) &&
                (!_cSharpUtilities.IsValidIdentifier(codeOptions.ContextName) ||
                 _cSharpUtilities.IsCSharpKeyword(codeOptions.ContextName)))
            {
                throw new ArgumentException(
                          DesignStrings.ContextClassNotValidCSharpIdentifier(codeOptions.ContextName));
            }

            var resolvedConnectionString = _connectionStringResolver.ResolveConnectionString(connectionString);

            if (resolvedConnectionString != connectionString)
            {
                codeOptions.SuppressConnectionStringWarning = true;
            }
            else if (!codeOptions.SuppressOnConfiguring)
            {
                _reporter.WriteWarning(DesignStrings.SensitiveInformationWarning);
            }

            if (codeOptions.ConnectionString == null)
            {
                codeOptions.ConnectionString = connectionString;
            }

            var databaseModel         = _databaseModelFactory.Create(resolvedConnectionString, databaseOptions);
            var modelConnectionString = (string?)(databaseModel[ScaffoldingAnnotationNames.ConnectionString]);

            if (!string.IsNullOrEmpty(modelConnectionString))
            {
                codeOptions.ConnectionString = modelConnectionString;
                databaseModel.RemoveAnnotation(ScaffoldingAnnotationNames.ConnectionString);
            }

            var model = _factory.Create(databaseModel, modelOptions);

            if (model == null)
            {
                throw new InvalidOperationException(
                          DesignStrings.ProviderReturnedNullModel(
                              _factory.GetType().ShortDisplayName()));
            }

            if (string.IsNullOrEmpty(codeOptions.ContextName))
            {
                var annotatedName = model.GetDatabaseName();
                codeOptions.ContextName = !string.IsNullOrEmpty(annotatedName)
                    ? _code.Identifier(annotatedName + DbContextSuffix)
                    : DefaultDbContextName;
            }

            var codeGenerator = ModelCodeGeneratorSelector.Select(codeOptions.Language);

            return(codeGenerator.GenerateModel(model, codeOptions));
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options)
        {
            Check.NotNull(databaseModel, nameof(databaseModel));
            Check.NotNull(options, nameof(options));

            var modelBuilder = new ModelBuilder();

            _tableNamer = new CSharpUniqueNamer <DatabaseTable>(
                options.UseDatabaseNames
                    ? (Func <DatabaseTable, string>)(t => t.Name)
                    : t => _candidateNamingService.GenerateCandidateIdentifier(t),
                _cSharpUtilities,
                options.NoPluralize
                    ? (Func <string, string>)null
                    : _pluralizer.Singularize);
            _dbSetNamer = new CSharpUniqueNamer <DatabaseTable>(
                options.UseDatabaseNames
                    ? (Func <DatabaseTable, string>)(t => t.Name)
                    : t => _candidateNamingService.GenerateCandidateIdentifier(t),
                _cSharpUtilities,
                options.NoPluralize
                    ? (Func <string, string>)null
                    : _pluralizer.Pluralize);
            _columnNamers = new Dictionary <DatabaseTable, CSharpUniqueNamer <DatabaseColumn> >();
            _options      = options;

            VisitDatabaseModel(modelBuilder, databaseModel);

            return(modelBuilder.Model);
        }
Example #3
0
        private ScaffoldedModel ScaffoldModel(
            string connectionString,
            DatabaseModelFactoryOptions databaseOptions,
            ModelReverseEngineerOptions modelOptions,
            ModelCodeGenerationOptions codeOptions,
            bool removeNullableBoolDefaults,
            bool excludeNavigations,
            bool dbContextOnly,
            bool entitiesOnly,
            bool useSchemaFolders)
        {
            var databaseModel = databaseModelFactory.Create(connectionString, databaseOptions);

            if (removeNullableBoolDefaults)
            {
                foreach (var column in databaseModel.Tables
                         .SelectMany(table => table.Columns
                                     .Where(column => (column.StoreType == "bit" || column.StoreType == "boolean") &&
                                            !column.IsNullable &&
                                            !string.IsNullOrEmpty(column.DefaultValueSql))))
                {
                    column.DefaultValueSql = null;
                }
            }

            if (excludeNavigations)
            {
                foreach (var table in databaseModel.Tables)
                {
                    table.ForeignKeys.Clear();
                }
            }

#if CORE50 || CORE60
            var model = factory.Create(databaseModel, modelOptions);
#else
            var model = factory.Create(databaseModel, modelOptions.UseDatabaseNames);
#endif
            if (model == null)
            {
                throw new InvalidOperationException($"No model from provider {factory.GetType().ShortDisplayName()}");
            }

            var codeGenerator = ModelCodeGeneratorSelector.Select(codeOptions.Language);

            var codeModel = codeGenerator.GenerateModel(model, codeOptions);
            if (entitiesOnly)
            {
                codeModel.ContextFile = null;
            }

            if (dbContextOnly)
            {
                codeModel.AdditionalFiles.Clear();
            }

            AppendSchemaFolders(model, codeModel, useSchemaFolders);

            return(codeModel);
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual ScaffoldedModel ScaffoldModel(
            string connectionString,
            DatabaseModelFactoryOptions options,
            string rootNamespace,
            string modelNamespace,
            string contextNamespace,
            string language,
            string contextDir,
            string contextName,
            ModelReverseEngineerOptions modelOptions,
            ModelCodeGenerationOptions codeOptions)
        {
            Check.NotEmpty(connectionString, nameof(connectionString));
            Check.NotNull(options, nameof(options));
            Check.NotEmpty(modelNamespace, nameof(modelNamespace));
            Check.NotEmpty(contextNamespace, nameof(contextNamespace));
            Check.NotNull(modelOptions, nameof(modelOptions));
            Check.NotNull(codeOptions, nameof(codeOptions));

            if (!string.IsNullOrWhiteSpace(contextName) &&
                (!_cSharpUtilities.IsValidIdentifier(contextName) ||
                 _cSharpUtilities.IsCSharpKeyword(contextName)))
            {
                throw new ArgumentException(
                          DesignStrings.ContextClassNotValidCSharpIdentifier(contextName));
            }

            var resolvedConnectionString = _connectionStringResolver.ResolveConnectionString(connectionString);

            if (resolvedConnectionString != connectionString)
            {
                codeOptions.SuppressConnectionStringWarning = true;
            }

            var databaseModel = _databaseModelFactory.Create(resolvedConnectionString, options);
            var model         = _factory.Create(databaseModel, modelOptions.UseDatabaseNames);

            if (model == null)
            {
                throw new InvalidOperationException(
                          DesignStrings.ProviderReturnedNullModel(
                              _factory.GetType().ShortDisplayName()));
            }

            if (string.IsNullOrEmpty(contextName))
            {
                contextName = DefaultDbContextName;

                var annotatedName = model.GetDatabaseName();
                if (!string.IsNullOrEmpty(annotatedName))
                {
                    contextName = _code.Identifier(annotatedName + DbContextSuffix);
                }
            }

            var codeGenerator = ModelCodeGeneratorSelector.Select(language);

            return(codeGenerator.GenerateModel(model, rootNamespace, modelNamespace, contextNamespace, contextDir ?? string.Empty, contextName, connectionString, codeOptions));
        }
Example #5
0
        public SavedModelFiles GenerateDbContext(
            ReverseEngineerCommandOptions options,
            List <string> schemas,
            string outputContextDir,
            string modelNamespace,
            string contextNamespace)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            SavedModelFiles filePaths;
            var             modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = options.UseDatabaseNames,
#if CORE50 || CORE60
                NoPluralize = !options.UseInflector,
#endif
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !options.UseFluentApiOnly,
                Language           = "C#",
                ContextName        = code.Identifier(options.ContextClassName),
                ContextDir         = outputContextDir,
                RootNamespace      = null,
                ContextNamespace   = contextNamespace,
                ModelNamespace     = modelNamespace,
                SuppressConnectionStringWarning = false,
                ConnectionString = options.ConnectionString,
#if CORE50 || CORE60
                SuppressOnConfiguring = !options.IncludeConnectionString,
#endif
#if CORE60
                UseNullableReferenceTypes = options.UseNullableReferences,
#endif
            };

            var dbOptions = new DatabaseModelFactoryOptions(options.Tables.Where(t => t.ObjectType.HasColumns()).Select(m => m.Name), schemas);

            var scaffoldedModel = ScaffoldModel(
                options.Dacpac ?? options.ConnectionString,
                dbOptions,
                modelOptions,
                codeOptions,
                options.UseBoolPropertiesWithoutDefaultSql,
                options.UseNoNavigations,
                options.SelectedToBeGenerated == 1,     // DbContext only
                options.SelectedToBeGenerated == 2,     // Entities only
                options.UseSchemaFolders);

            filePaths = Save(
                scaffoldedModel,
                Path.GetFullPath(Path.Combine(options.ProjectPath, options.OutputPath ?? string.Empty)));
            return(filePaths);
        }
    public override IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options)
    {
        foreach (var sequence in databaseModel.Sequences)
        {
            sequence.Database = databaseModel;
        }

        foreach (var table in databaseModel.Tables)
        {
            table.Database = databaseModel;

            foreach (var column in table.Columns)
            {
                column.Table = table;
            }

            if (table.PrimaryKey != null)
            {
                table.PrimaryKey.Table = table;
                FixupColumns(table, table.PrimaryKey.Columns);
            }

            foreach (var index in table.Indexes)
            {
                index.Table = table;
                FixupColumns(table, index.Columns);
            }

            foreach (var uniqueConstraints in table.UniqueConstraints)
            {
                uniqueConstraints.Table = table;
                FixupColumns(table, uniqueConstraints.Columns);
            }

            foreach (var foreignKey in table.ForeignKeys)
            {
                foreignKey.Table = table;
                FixupColumns(table, foreignKey.Columns);

                if (foreignKey.PrincipalTable is DatabaseTableRef tableRef)
                {
                    foreignKey.PrincipalTable = databaseModel.Tables
                                                .First(t => t.Name == tableRef.Name && t.Schema == tableRef.Schema);
                }

                FixupColumns(foreignKey.PrincipalTable, foreignKey.PrincipalColumns);
            }
        }

        return(base.Create(databaseModel, options));
    }
Example #7
0
        private static ScaffoldedModel ScaffoldModel(
            string connectionString,
            DatabaseModelFactoryOptions databaseOptions,
            ModelReverseEngineerOptions modelOptions,
            ModelCodeGenerationOptions codeOptions,
            bool removeNullableBoolDefaults,
            bool excludeNavigations,
            ServiceProvider serviceProvider)
        {
            var _databaseModelFactory = serviceProvider.GetService <IDatabaseModelFactory>();
            var _factory  = serviceProvider.GetService <IScaffoldingModelFactory>();
            var _selector = serviceProvider.GetService <IModelCodeGeneratorSelector>();

            var databaseModel = _databaseModelFactory.Create(connectionString, databaseOptions);

            if (removeNullableBoolDefaults)
            {
                foreach (var column in databaseModel.Tables
                         .SelectMany(table => table.Columns
                                     .Where(column => column.StoreType == "bit" &&
                                            !column.IsNullable &&
                                            !string.IsNullOrEmpty(column.DefaultValueSql))))
                {
                    column.DefaultValueSql = null;
                }
            }

            if (excludeNavigations)
            {
                foreach (var table in databaseModel.Tables)
                {
                    table.ForeignKeys.Clear();
                }
            }

#if CORE50
            var model = _factory.Create(databaseModel, modelOptions);
#else
            var model = _factory.Create(databaseModel, modelOptions.UseDatabaseNames);
#endif
            if (model == null)
            {
                throw new InvalidOperationException($"No model from provider {_factory.GetType().ShortDisplayName()}");
            }

            var codeGenerator = _selector.Select(codeOptions.Language);

            return(codeGenerator.GenerateModel(model, codeOptions));
        }
 //
 // 摘要:
 //     /// This API supports the Entity Framework Core infrastructure and is not intended
 //     to be used /// directly from your code. This API may change or be removed in
 //     future releases. ///
 public override ScaffoldedModel ScaffoldModel(string connectionString,
                                               IEnumerable <string> tables,
                                               IEnumerable <string> schemas,
                                               string @namespace,
                                               string language,
                                               string contextDir,
                                               string contextName,
                                               ModelReverseEngineerOptions modelOptions,
                                               ModelCodeGenerationOptions codeOptions)
 {
     if (tables == null || !tables.Any())
     {
         tables = HandlebarsScaffoldingOptions.Tables ?? new List <string>();
     }
     if (schemas == null || !schemas.Any())
     {
         schemas = HandlebarsScaffoldingOptions.Schemas ?? new List <string>();
     }
     return(base.ScaffoldModel(connectionString, tables, schemas, @namespace, language, contextDir, contextName, modelOptions, codeOptions));
 }
        public override IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options)
        {
            foreach (var sequence in databaseModel.Sequences)
            {
                sequence.Database = databaseModel;
            }

            foreach (var table in databaseModel.Tables)
            {
                table.Database = databaseModel;

                foreach (var column in table.Columns)
                {
                    column.Table = table;
                }

                if (table.PrimaryKey != null)
                {
                    table.PrimaryKey.Table = table;
                }

                foreach (var index in table.Indexes)
                {
                    index.Table = table;
                }

                foreach (var uniqueConstraints in table.UniqueConstraints)
                {
                    uniqueConstraints.Table = table;
                }

                foreach (var foreignKey in table.ForeignKeys)
                {
                    foreignKey.Table = table;
                }
            }

            return(base.Create(databaseModel, options));
        }
        public EfCoreReverseEngineerResult GenerateFiles(ReverseEngineerOptions reverseEngineerOptions)
        {
            var errors   = new List <string>();
            var warnings = new List <string>();
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => errors.Add(m),
                    m => warnings.Add(m)));

            // Add base services for scaffolding
            var serviceCollection = new ServiceCollection();

            serviceCollection
            .AddEntityFrameworkDesignTimeServices()
            .AddSingleton <IOperationReporter, OperationReporter>()
            .AddSingleton <IOperationReportHandler, OperationReportHandler>();

            if (reverseEngineerOptions.UseHandleBars)
            {
                //TODO Consider being selective based on SelectedToBeGenerated
                serviceCollection.AddHandlebarsScaffolding();
                serviceCollection.AddSingleton <ITemplateFileService>(provider => new CustomTemplateFileService(reverseEngineerOptions.ProjectPath));
            }

            if (reverseEngineerOptions.CustomReplacers != null)
            {
                serviceCollection.AddSingleton <ICandidateNamingService>(provider => new ReplacingCandidateNamingService(reverseEngineerOptions.CustomReplacers));
            }

            if (reverseEngineerOptions.UseInflector)
            {
                serviceCollection.AddSingleton <IPluralizer, InflectorPluralizer>();
            }

            // Add database provider services
            switch (reverseEngineerOptions.DatabaseType)
            {
            case DatabaseType.SQLCE35:
                throw new NotImplementedException();

            case DatabaseType.SQLCE40:
                var sqlCeProvider = new SqlCeDesignTimeServices();
                sqlCeProvider.ConfigureDesignTimeServices(serviceCollection);
                break;

            case DatabaseType.SQLServer:
                var provider = new SqlServerDesignTimeServices();
                provider.ConfigureDesignTimeServices(serviceCollection);

                var spatial = new SqlServerNetTopologySuiteDesignTimeServices();
                spatial.ConfigureDesignTimeServices(serviceCollection);

                if (!string.IsNullOrEmpty(reverseEngineerOptions.Dacpac))
                {
                    serviceCollection.AddSingleton <IDatabaseModelFactory, SqlServerDacpacDatabaseModelFactory>();
                }
                break;

            case DatabaseType.Npgsql:
                var npgsqlProvider = new NpgsqlDesignTimeServices();
                npgsqlProvider.ConfigureDesignTimeServices(serviceCollection);
                break;

            case DatabaseType.Mysql:
                var mysqlProvider = new MySqlDesignTimeServices();
                mysqlProvider.ConfigureDesignTimeServices(serviceCollection);
                break;

            case DatabaseType.SQLite:
                var sqliteProvider = new SqliteDesignTimeServices();
                sqliteProvider.ConfigureDesignTimeServices(serviceCollection);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var serviceProvider = serviceCollection.BuildServiceProvider();
            var scaffolder      = serviceProvider.GetService <IReverseEngineerScaffolder>();

            var schemas = new List <string>();

            if (reverseEngineerOptions.DefaultDacpacSchema != null)
            {
                schemas.Add(reverseEngineerOptions.DefaultDacpacSchema);
            }

            var @namespace = reverseEngineerOptions.ProjectRootNamespace;

            if (!string.IsNullOrEmpty(reverseEngineerOptions.OutputPath))
            {
                @namespace += "." + reverseEngineerOptions.OutputPath.Replace(Path.DirectorySeparatorChar, '.').Replace(Path.AltDirectorySeparatorChar, '.');
            }
            var modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = reverseEngineerOptions.UseDatabaseNames
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !reverseEngineerOptions.UseFluentApiOnly
            };

            var scaffoldedModel = scaffolder.ScaffoldModel(
                reverseEngineerOptions.Dacpac != null
                        ? reverseEngineerOptions.Dacpac
                        : reverseEngineerOptions.ConnectionString,
                reverseEngineerOptions.Tables.Select(m => m.Name).ToArray(),
                schemas,
                @namespace,
                "C#",
                null,
                reverseEngineerOptions.ContextClassName,
                modelOptions,
                codeOptions);

            var filePaths = scaffolder.Save(
                scaffoldedModel,
                Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath ?? string.Empty),
                overwriteFiles: true);

            PostProcessContext(filePaths.ContextFile, reverseEngineerOptions);

            foreach (var file in filePaths.AdditionalFiles)
            {
                PostProcess(file, reverseEngineerOptions.IdReplace);
            }
            PostProcess(filePaths.ContextFile, reverseEngineerOptions.IdReplace);

            var result = new EfCoreReverseEngineerResult
            {
                EntityErrors        = errors,
                EntityWarnings      = warnings,
                EntityTypeFilePaths = filePaths.AdditionalFiles,
                ContextFilePath     = filePaths.ContextFile,
            };

            return(result);
        }
        public ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions reverseEngineerOptions)
        {
            var errors = new List<string>();
            var warnings = new List<string>();
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => errors.Add(m),
                    m => warnings.Add(m)));

            var serviceProvider = ServiceProviderBuilder.Build(reverseEngineerOptions);
            var scaffolder = serviceProvider.GetService<IReverseEngineerScaffolder>();

            var schemas = new List<string>();
            if (reverseEngineerOptions.DefaultDacpacSchema != null)
            {
                schemas.Add(reverseEngineerOptions.DefaultDacpacSchema);
            }

            if (reverseEngineerOptions.FilterSchemas)
            {
                schemas.AddRange(reverseEngineerOptions.Schemas.Select(s => s.Name));
            }

            var outputDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputPath)
               ? Path.IsPathFullyQualified(reverseEngineerOptions.OutputPath)
                    ? reverseEngineerOptions.OutputPath
                    : Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath))
                : reverseEngineerOptions.ProjectPath;

            var outputContextDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputContextPath)
               ? Path.IsPathFullyQualified(reverseEngineerOptions.OutputContextPath)
                    ? reverseEngineerOptions.OutputContextPath
                    : Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputContextPath))
                : outputDir;

            var modelNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ModelNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ModelNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            var contextNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ContextNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ContextNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputContextDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            SavedModelFiles procedurePaths = null;
            var procedureModelScaffolder = serviceProvider.GetService<IProcedureScaffolder>();
            if (procedureModelScaffolder != null
                && reverseEngineerOptions.Tables.Where(t => t.ObjectType == RevEng.Shared.ObjectType.Procedure).Count() > 0)
            {
                var procedureOptions = new ProcedureScaffolderOptions
                {
                    ContextDir = outputContextDir,
                    ContextName = reverseEngineerOptions.ContextClassName,
                    ContextNamespace = contextNamespace,
                    ModelNamespace = modelNamespace,
                };

                var procedureModelOptions = new ProcedureModelFactoryOptions
                {
                    FullModel = true,
                    Procedures = reverseEngineerOptions.Tables.Where(t => t.ObjectType == RevEng.Shared.ObjectType.Procedure).Select(m => m.Name),
                };

                var procedureModel = procedureModelScaffolder.ScaffoldModel(reverseEngineerOptions.ConnectionString, procedureOptions, procedureModelOptions, ref errors);

                if (procedureModel != null)
                {
                    procedurePaths = procedureModelScaffolder.Save(
                        procedureModel,
                        Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath ?? string.Empty)),
                        contextNamespace);
                }
            }

            var modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = reverseEngineerOptions.UseDatabaseNames,
#if CORE50
                NoPluralize = !reverseEngineerOptions.UseInflector,
#endif
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !reverseEngineerOptions.UseFluentApiOnly,
                Language = "C#",
                ContextName = reverseEngineerOptions.ContextClassName,
                ContextDir = outputContextDir,
                RootNamespace = null,
                ContextNamespace = contextNamespace,
                ModelNamespace = modelNamespace,
                SuppressConnectionStringWarning = false,
                ConnectionString = reverseEngineerOptions.ConnectionString,
#if CORE50
                SuppressOnConfiguring = !reverseEngineerOptions.IncludeConnectionString,
#endif
            };

            var dbOptions = new DatabaseModelFactoryOptions(reverseEngineerOptions.Tables.Where(t => t.ObjectType.HasColumns()).Select(m => m.Name), schemas);

            var scaffoldedModel = scaffolder.ScaffoldModel(
                    reverseEngineerOptions.Dacpac ?? reverseEngineerOptions.ConnectionString,
                    dbOptions,
                    modelOptions,
                    codeOptions);

            var filePaths = scaffolder.Save(
                scaffoldedModel,
                Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath ?? string.Empty)),
                overwriteFiles: true);

#if CORE50
#else
            RemoveOnConfiguring(filePaths.ContextFile, reverseEngineerOptions.IncludeConnectionString);
#endif
            foreach (var file in filePaths.AdditionalFiles)
            {
                PostProcess(file);
            }

            PostProcess(filePaths.ContextFile);

            var entityTypeConfigurationPaths = SplitDbContext(filePaths.ContextFile, reverseEngineerOptions.UseDbContextSplitting, contextNamespace);

            var cleanUpPaths = new SavedModelFiles(filePaths.ContextFile, filePaths.AdditionalFiles);
            if (procedurePaths != null)
            {
                cleanUpPaths.AdditionalFiles.Add(procedurePaths.ContextFile);
                foreach (var additionalFile in procedurePaths.AdditionalFiles)
                {
                    cleanUpPaths.AdditionalFiles.Add(additionalFile);
                }
            }

            CleanUp(cleanUpPaths, entityTypeConfigurationPaths);

            var result = new ReverseEngineerResult
            {
                EntityErrors = errors,
                EntityWarnings = warnings,
                EntityTypeFilePaths = filePaths.AdditionalFiles,
                ContextFilePath = filePaths.ContextFile,
                ContextConfigurationFilePaths = entityTypeConfigurationPaths,
            };

            return result;
        }
Example #12
0
        public ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions reverseEngineerOptions)
        {
            var errors   = new List <string>();
            var warnings = new List <string>();
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => errors.Add(m),
                    m => warnings.Add(m)));

            var serviceProvider = ServiceProviderBuilder.Build(reverseEngineerOptions);
            var scaffolder      = serviceProvider.GetService <IReverseEngineerScaffolder>();

            var schemas = new List <string>();

            if (reverseEngineerOptions.DefaultDacpacSchema != null)
            {
                schemas.Add(reverseEngineerOptions.DefaultDacpacSchema);
            }

            var outputDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputPath)
               ? Path.IsPathFullyQualified(reverseEngineerOptions.OutputPath)
                    ? reverseEngineerOptions.OutputPath
                    : Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath))
                : reverseEngineerOptions.ProjectPath;

            var outputContextDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputContextPath)
               ? Path.IsPathFullyQualified(reverseEngineerOptions.OutputContextPath)
                    ? reverseEngineerOptions.OutputContextPath
                    : Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputContextPath))
                : outputDir;

            var modelNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ModelNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ModelNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            var contextNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ContextNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ContextNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputContextDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            var modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = reverseEngineerOptions.UseDatabaseNames,
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !reverseEngineerOptions.UseFluentApiOnly,
                Language           = "C#",
                ContextName        = reverseEngineerOptions.ContextClassName,
                ContextDir         = outputContextDir,
                RootNamespace      = null,
                ContextNamespace   = contextNamespace,
                ModelNamespace     = modelNamespace,
                SuppressConnectionStringWarning = false,
                ConnectionString = reverseEngineerOptions.ConnectionString,
            };

            var dbOptions = new DatabaseModelFactoryOptions(reverseEngineerOptions.Tables.Select(m => m.Name), schemas);

            var scaffoldedModel = scaffolder.ScaffoldModel(
                reverseEngineerOptions.Dacpac ?? reverseEngineerOptions.ConnectionString,
                dbOptions,
                modelOptions,
                codeOptions);

            var filePaths = scaffolder.Save(
                scaffoldedModel,
                Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath ?? string.Empty),
                overwriteFiles: true);

            string fixedNamespace = modelNamespace != contextNamespace
                ? modelNamespace
                : null;

            PostProcessContext(filePaths.ContextFile, reverseEngineerOptions, fixedNamespace);

            foreach (var file in filePaths.AdditionalFiles)
            {
                PostProcess(file);
            }

            PostProcess(filePaths.ContextFile);

            var result = new ReverseEngineerResult
            {
                EntityErrors        = errors,
                EntityWarnings      = warnings,
                EntityTypeFilePaths = filePaths.AdditionalFiles,
                ContextFilePath     = filePaths.ContextFile,
            };

            return(result);
        }
Example #13
0
        static void Main(string[] args)
        {
            var connectionString = args.Length > 0
                ? args[0]
                : throw new Exception("Pass connection string as a first parameter");

            var scaffolder = CreateMssqlScaffolder();

            var dbOpts      = new DatabaseModelFactoryOptions();
            var modelOpts   = new ModelReverseEngineerOptions();
            var codeGenOpts = new ModelCodeGenerationOptions()
            {
                RootNamespace    = "TypedDataContext",
                ContextName      = "DataContext",
                ContextNamespace = "TypedDataContext.Context",
                ModelNamespace   = "TypedDataContext.Models",
                SuppressConnectionStringWarning = true
            };

            var scaffoldedModelSources = scaffolder.ScaffoldModel(connectionString, dbOpts, modelOpts, codeGenOpts);
            var sourceFiles            = new List <string> {
                scaffoldedModelSources.ContextFile.Code
            };

            sourceFiles.AddRange(scaffoldedModelSources.AdditionalFiles.Select(f => f.Code));

            using var peStream = new MemoryStream();

            var enableLazyLoading = false;
            var result            = GenerateCode(sourceFiles, enableLazyLoading).Emit(peStream);

            if (!result.Success)
            {
                var failures = result.Diagnostics
                               .Where(diagnostic => diagnostic.IsWarningAsError ||
                                      diagnostic.Severity == DiagnosticSeverity.Error);

                var error = failures.FirstOrDefault();
                throw new Exception($"{error?.Id}: {error?.GetMessage()}");
            }

            var assemblyLoadContext = new AssemblyLoadContext("DbContext", isCollectible: !enableLazyLoading);

            peStream.Seek(0, SeekOrigin.Begin);
            var assembly = assemblyLoadContext.LoadFromStream(peStream);

            var type = assembly.GetType("TypedDataContext.Context.DataContext");

            _ = type ?? throw new Exception("DataContext type not found");

            var constr = type.GetConstructor(Type.EmptyTypes);

            _ = constr ?? throw new Exception("DataContext ctor not found");

            DbContext dynamicContext = (DbContext)constr.Invoke(null);
            var       entityTypes    = dynamicContext.Model.GetEntityTypes();

            Console.WriteLine($"Context contains {entityTypes.Count()} types");

            foreach (var entityType in dynamicContext.Model.GetEntityTypes())
            {
                var items = (IQueryable <object>)dynamicContext.Query(entityType.Name);

                Console.WriteLine($"Entity type: {entityType.Name} contains {items.Count()} items");
            }

            Console.ReadKey();

            if (!enableLazyLoading)
            {
                assemblyLoadContext.Unload();
            }
        }
Example #14
0
        public ReverseEngineerResult GenerateFiles(ReverseEngineerOptions reverseEngineerOptions, bool includeViews)
        {
            if (includeViews)
            {
                return(LaunchExternalRunner(reverseEngineerOptions));
            }

            var errors   = new List <string>();
            var warnings = new List <string>();
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => errors.Add(m),
                    m => warnings.Add(m)));

            var serviceProvider = ServiceProviderBuilder.Build(reverseEngineerOptions);
            var scaffolder      = serviceProvider.GetService <IReverseEngineerScaffolder>();

            var schemas = new List <string>();

            if (reverseEngineerOptions.DefaultDacpacSchema != null)
            {
                schemas.Add(reverseEngineerOptions.DefaultDacpacSchema);
            }

            var outputDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputPath)
               ? Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath))
               : reverseEngineerOptions.ProjectPath;

            var outputContextDir = !string.IsNullOrEmpty(reverseEngineerOptions.OutputContextPath)
                ? Path.GetFullPath(Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputContextPath))
                : outputDir;

            var modelNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ModelNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ModelNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            var contextNamespace = !string.IsNullOrEmpty(reverseEngineerOptions.ContextNamespace)
                ? reverseEngineerOptions.ProjectRootNamespace + "." + reverseEngineerOptions.ContextNamespace
                : PathHelper.GetNamespaceFromOutputPath(outputContextDir, reverseEngineerOptions.ProjectPath, reverseEngineerOptions.ProjectRootNamespace);

            var modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = reverseEngineerOptions.UseDatabaseNames
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !reverseEngineerOptions.UseFluentApiOnly
            };

            var scaffoldedModel = scaffolder.ScaffoldModel(
                reverseEngineerOptions.Dacpac != null
                        ? reverseEngineerOptions.Dacpac
                        : reverseEngineerOptions.ConnectionString,
                reverseEngineerOptions.Tables.Select(m => m.Name).ToArray(),
                schemas,
                modelNamespace,
                "C#",
                outputContextDir,
                reverseEngineerOptions.ContextClassName,
                modelOptions,
                codeOptions);

            var filePaths = scaffolder.Save(
                scaffoldedModel,
                outputDir,
                overwriteFiles: true);

            PostProcessContext(filePaths.ContextFile, reverseEngineerOptions, modelNamespace, contextNamespace);

            foreach (var file in filePaths.AdditionalFiles)
            {
                PostProcess(file, reverseEngineerOptions.IdReplace);
            }

            PostProcess(filePaths.ContextFile, reverseEngineerOptions.IdReplace);

            CleanUp(filePaths);

            var result = new ReverseEngineerResult
            {
                EntityErrors        = errors,
                EntityWarnings      = warnings,
                EntityTypeFilePaths = filePaths.AdditionalFiles,
                ContextFilePath     = filePaths.ContextFile,
            };

            return(result);
        }
        public EfCoreReverseEngineerResult GenerateFiles(ReverseEngineerOptions reverseEngineerOptions)
        {
            var errors   = new List <string>();
            var warnings = new List <string>();
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => errors.Add(m),
                    m => warnings.Add(m)));

            var serviceProvider = ServiceProviderBuilder.Build(reverseEngineerOptions);
            var scaffolder      = serviceProvider.GetService <IReverseEngineerScaffolder>();

            var schemas = new List <string>();

            if (reverseEngineerOptions.DefaultDacpacSchema != null)
            {
                schemas.Add(reverseEngineerOptions.DefaultDacpacSchema);
            }

            var @namespace = reverseEngineerOptions.ProjectRootNamespace;

            if (!string.IsNullOrEmpty(reverseEngineerOptions.OutputPath) && !reverseEngineerOptions.DoNotCombineNamespace)
            {
                @namespace += "." + reverseEngineerOptions.OutputPath.Replace(Path.DirectorySeparatorChar, '.').Replace(Path.AltDirectorySeparatorChar, '.');
            }
            var modelOptions = new ModelReverseEngineerOptions
            {
                UseDatabaseNames = reverseEngineerOptions.UseDatabaseNames
            };

            var codeOptions = new ModelCodeGenerationOptions
            {
                UseDataAnnotations = !reverseEngineerOptions.UseFluentApiOnly
            };

            var scaffoldedModel = scaffolder.ScaffoldModel(
                reverseEngineerOptions.Dacpac != null
                        ? reverseEngineerOptions.Dacpac
                        : reverseEngineerOptions.ConnectionString,
                reverseEngineerOptions.Tables.Select(m => m.Name).ToArray(),
                schemas,
                @namespace,
                "C#",
                null,
                reverseEngineerOptions.ContextClassName,
                modelOptions,
                codeOptions);

            var filePaths = scaffolder.Save(
                scaffoldedModel,
                Path.Combine(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath ?? string.Empty),
                overwriteFiles: true);

            PostProcessContext(filePaths.ContextFile, reverseEngineerOptions);

            foreach (var file in filePaths.AdditionalFiles)
            {
                PostProcess(file, reverseEngineerOptions.IdReplace);
            }
            PostProcess(filePaths.ContextFile, reverseEngineerOptions.IdReplace);

            var result = new EfCoreReverseEngineerResult
            {
                EntityErrors        = errors,
                EntityWarnings      = warnings,
                EntityTypeFilePaths = filePaths.AdditionalFiles,
                ContextFilePath     = filePaths.ContextFile,
            };

            return(result);
        }
Example #16
0
        //public ScaffoldedModel ScaffoldModel(string connectionString, IEnumerable<string> tables, IEnumerable<string> schemas, string @namespace,
        //    string language, string contextDir, string contextName, ModelReverseEngineerOptions modelOptions,
        //    ModelCodeGenerationOptions codeOptions)
        //{
        //    var fullTables = tables.Select(x => new EntityType { FileName = x, DisplayName = x, Name = x }).ToList();

        //    return ScaffoldModel(connectionString, fullTables, schemas, @namespace, language, contextDir, contextName,
        //        modelOptions, codeOptions);

        //}

        public ScaffoldedModel ScaffoldModel(string connectionString, [NoEnumeration] IEnumerable <EntityType> tables, IEnumerable <string> schemas, string @namespace,
                                             string language, string contextDir, string contextName, ModelReverseEngineerOptions modelOptions,
                                             ModelCodeGenerationOptions codeOptions)
        {
            var entityTypes = tables.ToList();
            var resolvedConnectionString = _connectionStringResolver.ResolveConnectionString(connectionString);

            if (resolvedConnectionString != connectionString)
            {
                codeOptions.SuppressConnectionStringWarning = true;
            }

            var databaseModel = _databaseModelFactory.Create(resolvedConnectionString, entityTypes.Select(x => x.Name).ToList(), schemas);

            var customDatabaseModel = CreateCustomDatabaseModel(databaseModel, entityTypes);
            var model = _scaffoldingModelFactory.Create(customDatabaseModel, modelOptions.UseDatabaseNames);

            if (model == null)
            {
                // TODO: thow some other proper exception
                throw new Exception("Model is null");
                //throw new InvalidOperationException(
                //    DesignStrings.ProviderReturnedNullModel(
                //        _factory.GetType().ShortDisplayName()));
            }

            // TODO: Handle what to do when the contextName is empty
            //if (string.IsNullOrEmpty(contextName))
            //{
            //    contextName = DefaultDbContextName;

            //    var annotatedName = model.Scaffolding().DatabaseName;
            //    if (!string.IsNullOrEmpty(annotatedName))
            //    {
            //        contextName = _cSharpHelper.Identifier(annotatedName + DbContextSuffix);
            //    }
            //}

            var codeGenerator = _modelCodeGeneratorSelector.Select(language);

            return(codeGenerator.GenerateModel(model, @namespace, contextDir ?? string.Empty, contextName, connectionString, codeOptions));
        }