private MigrationsScaffolder CreateMigrationsScaffolder(DbContext context)
        {
            var logger = this.app.GetLogHub();

            var reporter = new OperationReporter(new OperationReportHandler(
                                                     m => logger.Error(m),
                                                     m => logger.Warning(m),
                                                     m => logger.Info(m),
                                                     m => logger.Trace(m)));

            var designTimeServices = new ServiceCollection()
                                     .AddSingleton(context.GetService <IHistoryRepository>())
                                     .AddSingleton(context.GetService <IMigrationsIdGenerator>())
                                     .AddSingleton(context.GetService <IMigrationsModelDiffer>())
                                     .AddSingleton(context.GetService <IMigrationsAssembly>())
                                     .AddSingleton(context.Model)
                                     .AddSingleton(context.GetService <ICurrentDbContext>())
                                     .AddSingleton(context.GetService <IDatabaseProvider>())
                                     .AddSingleton <MigrationsCodeGeneratorDependencies>()
                                     .AddSingleton <ICSharpHelper, CSharpHelper>()
                                     .AddSingleton <CSharpMigrationOperationGeneratorDependencies>()
                                     .AddSingleton <ICSharpMigrationOperationGenerator, CSharpMigrationOperationGenerator>()
                                     .AddSingleton <CSharpSnapshotGeneratorDependencies>()
                                     .AddSingleton <ICSharpSnapshotGenerator, CSharpSnapshotGenerator>()
                                     .AddSingleton <CSharpMigrationsGeneratorDependencies>()
                                     .AddSingleton <IMigrationsCodeGenerator, CSharpMigrationsGenerator>()
                                     .AddSingleton <ISnapshotModelProcessor, SnapshotModelProcessor>()
                                     .AddSingleton <IOperationReporter>(reporter)
                                     .AddSingleton <MigrationsScaffolderDependencies>()
                                     .AddSingleton <MigrationsScaffolder>()
                                     .BuildServiceProvider();

            return(designTimeServices.GetRequiredService <MigrationsScaffolder>());
        }
        private static void ValidateMigrationAndSnapshotCode(
            DbContext context,
            MigrationCodeGetter migrationCodeGetter,
            SnapshotCodeGetter snapshotCodeGetter)
        {
            const string migrationName = "MyMigration";
            const string rootNamespace = "MyApp.Data";

            var expectedMigration = migrationCodeGetter(migrationName, rootNamespace);
            var expectedSnapshot  = snapshotCodeGetter(rootNamespace);

            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => Console.WriteLine($"  error: {m}"),
                    m => Console.WriteLine($"   warn: {m}"),
                    m => Console.WriteLine($"   info: {m}"),
                    m => Console.WriteLine($"verbose: {m}")));

            var assembly = System.Reflection.Assembly.GetExecutingAssembly();

            //this works because we have placed the DesignTimeServicesReferenceAttribute
            //in the test project's properties, which simulates
            //the nuget package's build target
            var migration = new DesignTimeServicesBuilder(assembly, assembly, reporter, Array.Empty <string>())
                            .Build(context)
                            .GetRequiredService <IMigrationsScaffolder>()
                            .ScaffoldMigration(migrationName, rootNamespace);

            Assert.Equal(expectedMigration, migration.MigrationCode);
            Assert.Equal(expectedSnapshot, migration.SnapshotCode);
        }
Пример #3
0
        /// <summary>
        ///     <para>Initializes a new instance of the <see cref="OperationExecutor" /> class.</para>
        ///     <para>The arguments supported by <paramref name="args" /> are:</para>
        ///     <para><c>targetName</c>--The assembly name of the target project.</para>
        ///     <para><c>startupTargetName</c>--The assembly name of the startup project.</para>
        ///     <para><c>projectDir</c>--The target project's root directory.</para>
        ///     <para><c>rootNamespace</c>--The target project's root namespace.</para>
        /// </summary>
        /// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
        /// <param name="args"> The executor arguments. </param>
        public OperationExecutor([NotNull] object reportHandler, [NotNull] IDictionary args)
        {
            Check.NotNull(reportHandler, nameof(reportHandler));
            Check.NotNull(args, nameof(args));

            var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(reportHandler);

            _reporter          = new OperationReporter(unwrappedReportHandler);
            _targetName        = (string)args["targetName"];
            _startupTargetName = (string)args["startupTargetName"];
            _projectDir        = (string)args["projectDir"];
            _rootNamespace     = (string)args["rootNamespace"];
            _language          = (string)args["language"];

            // TODO: Flow in from tools (issue #8332)
            _designArgs = Array.Empty <string>();

            var toolsVersion   = (string)args["toolsVersion"];
            var runtimeVersion = ProductInfo.GetVersion();

            if (toolsVersion != null &&
                new SemanticVersionComparer().Compare(toolsVersion, runtimeVersion) < 0)
            {
                _reporter.WriteWarning(DesignStrings.VersionMismatch(toolsVersion, runtimeVersion));
            }
        }
Пример #4
0
        /// <summary>
        ///     <para>Initializes a new instance of the <see cref="OperationExecutor" /> class.</para>
        ///     <para>The arguments supported by <paramref name="args" /> are:</para>
        ///     <para><c>targetName</c>--The assembly name of the target project.</para>
        ///     <para><c>startupTargetName</c>--The assembly name of the startup project.</para>
        ///     <para><c>projectDir</c>--The target project's root directory.</para>
        ///     <para><c>rootNamespace</c>--The target project's root namespace.</para>
        /// </summary>
        /// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
        /// <param name="args"> The executor arguments. </param>
        public OperationExecutor([NotNull] object reportHandler, [NotNull] IDictionary args)
        {
            Check.NotNull(reportHandler, nameof(reportHandler));
            Check.NotNull(args, nameof(args));

            var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(reportHandler);
            var reporter = new OperationReporter(unwrappedReportHandler);

            var targetName        = (string)args["targetName"];
            var startupTargetName = (string)args["startupTargetName"];

            _projectDir = (string)args["projectDir"];
            var rootNamespace = (string)args["rootNamespace"];
            var language      = (string)args["language"];

            // TODO: Flow in from tools (issue #8332)
            var designArgs = Array.Empty <string>();

            // NOTE: LazyRef is used so any exceptions get passed to the resultHandler
            var startupAssembly = new LazyRef <Assembly>(
                () => Assembly.Load(new AssemblyName(startupTargetName)));
            var assembly = new LazyRef <Assembly>(
                () =>
            {
                try
                {
                    return(Assembly.Load(new AssemblyName(targetName)));
                }
                catch (Exception ex)
                {
                    throw new OperationException(
                        DesignStrings.UnreferencedAssembly(targetName, startupTargetName),
                        ex);
                }
            });

            _contextOperations = new LazyRef <DbContextOperations>(
                () => new DbContextOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    designArgs));
            _databaseOperations = new LazyRef <DatabaseOperations>(
                () => new DatabaseOperations(
                    reporter,
                    startupAssembly.Value,
                    _projectDir,
                    rootNamespace,
                    language,
                    designArgs));
            _migrationsOperations = new LazyRef <MigrationsOperations>(
                () => new MigrationsOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    _projectDir,
                    rootNamespace,
                    language,
                    designArgs));
        }
        private DbContextOperations GetOperations(string outputPath, string startupOutputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            Assembly startupAssembly = null;

            if (startupOutputPath != outputPath)
            {
                startupAssembly = Load(startupOutputPath);
            }

            var reporter = new OperationReporter(
                new OperationReportHandler());

#if CORE60
            //TODO Collect project, rootNamespace,language and nullable for optimize later
            return(new DbContextOperations(reporter, assembly, startupAssembly ?? assembly, outputPath, null, null, false, Array.Empty <string>()));
#else
            return(new DbContextOperations(reporter, assembly, startupAssembly ?? assembly, Array.Empty <string>()));
#endif
        }
Пример #6
0
        private static DbContextOperations GetOperations(string outputPath, string startupOutputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            Assembly startupAssembly = null;

            if (startupOutputPath != outputPath)
            {
                startupAssembly = Load(startupOutputPath);
            }

            var reporter = new OperationReporter(
                new OperationReportHandler());

#if CORE60
            return(new DbContextOperations(reporter, assembly, startupAssembly ?? assembly, outputPath, null, null, false, Array.Empty <string>()));
#else
            return(new DbContextOperations(reporter, assembly, startupAssembly ?? assembly, Array.Empty <string>()));
#endif
        }
Пример #7
0
        public List <Tuple <string, string> > GenerateDebugView(string outputPath)
        {
            var result = new List <Tuple <string, string> >();

            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            var reporter = new OperationReporter(
                new OperationReportHandler());

            var operations = new DbContextOperations(reporter, assembly, assembly);
            var types      = operations.GetContextTypes().ToList();

            if (types.Count == 0)
            {
                throw new ArgumentException("No DbContext types found in the project");
            }

            foreach (var type in types)
            {
                var dbContext = operations.CreateContext(types[0].Name);
                var debugView = dbContext.Model.AsModel().DebugView.View;
                result.Add(new Tuple <string, string>(type.Name, debugView));
            }

            return(result);
        }
Пример #8
0
        public static ScaffoldedModel ScaffoldContext(
            [NotNull] string provider,
            [NotNull] string connectionString,
            [CanBeNull] string outputDir,
            [CanBeNull] string outputContextDir,
            [CanBeNull] string dbContextClassName,
            [NotNull] IEnumerable <string> schemas,
            [NotNull] IEnumerable <string> tables,
            bool useDataAnnotations,
            bool overwriteFiles,
            bool useDatabaseNames)
        {
            var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(new OperationReportHandler());
            var reporter         = new OperationReporter(unwrappedReportHandler);
            var _servicesBuilder = new DesignTimeServicesBuilder(Assembly.GetExecutingAssembly(), reporter, Array.Empty <string>());
            var services         = _servicesBuilder.Build(provider);
            var scaffolder       = services.GetRequiredService <IReverseEngineerScaffolder>();
            var @namespace       = "DiplomWork";
            var scaffoldedModel  = scaffolder.ScaffoldModel(
                connectionString,
                tables,
                schemas,
                @namespace,
                null,
                MakeDirRelative(outputDir, outputContextDir),
                dbContextClassName,
                new ModelReverseEngineerOptions {
                UseDatabaseNames = useDatabaseNames
            },
                new ModelCodeGenerationOptions {
                UseDataAnnotations = useDataAnnotations
            });

            return(scaffoldedModel);
        }
Пример #9
0
        public OperationExecutor([NotNull] object reportHandler, [NotNull] IDictionary args)
        {
            Check.NotNull(reportHandler, nameof(reportHandler));
            Check.NotNull(args, nameof(args));

            var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(reportHandler);
            var reporter = new OperationReporter(unwrappedReportHandler);

            var targetName        = (string)args["targetName"];
            var startupTargetName = (string)args["startupTargetName"];
            var environment       = (string)args["environment"];

            _projectDir = (string)args["projectDir"];
            var contentRootPath = (string)args["contentRootPath"];
            var rootNamespace   = (string)args["rootNamespace"];

            // NOTE: LazyRef is used so any exceptions get passed to the resultHandler
            var startupAssembly = new LazyRef <Assembly>(
                () => Assembly.Load(new AssemblyName(startupTargetName)));
            var assembly = new LazyRef <Assembly>(
                () =>
            {
                try
                {
                    return(Assembly.Load(new AssemblyName(targetName)));
                }
                catch (Exception ex)
                {
                    throw new OperationException(
                        DesignStrings.UnreferencedAssembly(targetName, startupTargetName),
                        ex);
                }
            });

            _contextOperations = new LazyRef <DbContextOperations>(
                () => new DbContextOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    environment,
                    contentRootPath));
            _databaseOperations = new LazyRef <DatabaseOperations>(
                () => new DatabaseOperations(
                    reporter,
                    startupAssembly.Value,
                    environment,
                    _projectDir,
                    contentRootPath,
                    rootNamespace));
            _migrationsOperations = new LazyRef <MigrationsOperations>(
                () => new MigrationsOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    environment,
                    _projectDir,
                    contentRootPath,
                    rootNamespace));
        }
        /// <summary>
        ///     Adds the Entity Framework Core design-time services.
        /// </summary>
        /// <param name="services"> The <see cref="IServiceCollection" /> the services will be added to. </param>
        /// <param name="reporter"> Used to report design-time messages. </param>
        /// <param name="applicationServiceProviderAccessor"> An accessor to the application service provider. </param>
        /// <returns> The <paramref name="services" />. This enables chaining additional method calls. </returns>
        public static IServiceCollection AddEntityFrameworkDesignTimeServices(
            [NotNull] this IServiceCollection services,
            [CanBeNull] IOperationReporter reporter = null,
            [CanBeNull] Func <IServiceProvider> applicationServiceProviderAccessor = null)
        {
            if (reporter == null)
            {
                reporter = new OperationReporter(handler: null);
            }

            return(services
                   .AddSingleton <AnnotationCodeGeneratorDependencies>()
                   .AddSingleton <TypeMappingSourceDependencies>()
                   .AddSingleton <CSharpMigrationOperationGeneratorDependencies>()
                   .AddSingleton <CSharpMigrationsGeneratorDependencies>()
                   .AddSingleton <CSharpSnapshotGeneratorDependencies>()
                   .AddSingleton <MigrationsCodeGeneratorDependencies>()
                   .AddSingleton <ModelCodeGeneratorDependencies>()
                   .AddSingleton <ProviderCodeGeneratorDependencies>()
                   .AddSingleton <TypeMappingSourceDependencies>()
                   .AddSingleton <RelationalTypeMappingSourceDependencies>()
                   .AddSingleton <ValueConverterSelectorDependencies>()
                   .AddSingleton <ICandidateNamingService, CandidateNamingService>()
                   .AddSingleton <ICSharpDbContextGenerator, CSharpDbContextGenerator>()
                   .AddSingleton <ICSharpEntityTypeGenerator, CSharpEntityTypeGenerator>()
                   .AddSingleton <ICSharpHelper, CSharpHelper>()
                   .AddSingleton <ICSharpMigrationOperationGenerator, CSharpMigrationOperationGenerator>()
                   .AddSingleton <ICSharpSnapshotGenerator, CSharpSnapshotGenerator>()
                   .AddSingleton <ICSharpUtilities, CSharpUtilities>()
                   .AddSingleton(typeof(IDiagnosticsLogger <>), typeof(DiagnosticsLogger <>))
                   .AddSingleton <IInterceptors, Interceptors>()
                   .AddSingleton <DiagnosticSource>(new DiagnosticListener(DbLoggerCategory.Name))
                   .AddSingleton <ILoggingOptions, LoggingOptions>()
                   .AddSingleton <IMigrationsCodeGenerator, CSharpMigrationsGenerator>()
                   .AddSingleton <IMigrationsCodeGeneratorSelector, MigrationsCodeGeneratorSelector>()
                   .AddSingleton <IModelCodeGenerator, CSharpModelGenerator>()
                   .AddSingleton <IModelCodeGeneratorSelector, ModelCodeGeneratorSelector>()
                   .AddSingleton <IAnnotationCodeGenerator, AnnotationCodeGenerator>()
                   .AddSingleton <INamedConnectionStringResolver>(
                       new DesignTimeConnectionStringResolver(applicationServiceProviderAccessor))
                   .AddSingleton(reporter)
                   .AddSingleton <IPluralizer, HumanizerPluralizer>()
                   .AddSingleton <IReverseEngineerScaffolder, ReverseEngineerScaffolder>()
                   .AddSingleton <IScaffoldingModelFactory, RelationalScaffoldingModelFactory>()
                   .AddSingleton <IScaffoldingTypeMapper, ScaffoldingTypeMapper>()
                   .AddSingleton <IValueConverterSelector, ValueConverterSelector>()
                   .AddSingleton <IDbContextLogger, NullDbContextLogger>()
                   .AddTransient <MigrationsScaffolderDependencies>()
                   .AddTransient <IMigrationsScaffolder, MigrationsScaffolder>()
                   .AddTransient <ISnapshotModelProcessor, SnapshotModelProcessor>()
                   .AddLogging(b => b.SetMinimumLevel(LogLevel.Debug).AddProvider(new OperationLoggerProvider(reporter))));
        }
    /// <summary>
    ///     Adds the Entity Framework Core design-time services.
    /// </summary>
    /// <remarks>
    ///     See <see href="https://aka.ms/efcore-docs-design-time-services">EF Core design-time services</see> for more information and examples.
    /// </remarks>
    /// <param name="services">The <see cref="IServiceCollection" /> the services will be added to.</param>
    /// <param name="reporter">Used to report design-time messages.</param>
    /// <param name="applicationServiceProviderAccessor">An accessor to the application service provider.</param>
    /// <returns>The <paramref name="services" />. This enables chaining additional method calls.</returns>
    public static IServiceCollection AddEntityFrameworkDesignTimeServices(
        this IServiceCollection services,
        IOperationReporter?reporter = null,
        Func <IServiceProvider>?applicationServiceProviderAccessor = null)
    {
        if (reporter == null)
        {
            reporter = new OperationReporter(handler: null);
        }

        new EntityFrameworkRelationalDesignServicesBuilder(services)
        .TryAddProviderSpecificServices(
            services => services
            .TryAddSingleton <CSharpMigrationOperationGeneratorDependencies, CSharpMigrationOperationGeneratorDependencies>()
            .TryAddSingleton <CSharpMigrationsGeneratorDependencies, CSharpMigrationsGeneratorDependencies>()
            .TryAddSingleton <CSharpSnapshotGeneratorDependencies, CSharpSnapshotGeneratorDependencies>()
            .TryAddSingleton <ICandidateNamingService, CandidateNamingService>()
            .TryAddSingleton <ICSharpDbContextGenerator, CSharpDbContextGenerator>()
            .TryAddSingleton <ICSharpEntityTypeGenerator, CSharpEntityTypeGenerator>()
            .TryAddSingleton <ICSharpHelper, CSharpHelper>()
            .TryAddSingleton <ICSharpMigrationOperationGenerator, CSharpMigrationOperationGenerator>()
            .TryAddSingleton <ICSharpSnapshotGenerator, CSharpSnapshotGenerator>()
            .TryAddSingleton <ICSharpUtilities, CSharpUtilities>()
            .TryAddSingleton(reporter)
            .TryAddSingleton <IMigrationsCodeGenerator, CSharpMigrationsGenerator>()
            .TryAddSingleton <IMigrationsCodeGeneratorSelector, MigrationsCodeGeneratorSelector>()
            .TryAddSingleton <IModelCodeGenerator, CSharpModelGenerator>()
            .TryAddSingleton <IModelCodeGeneratorSelector, ModelCodeGeneratorSelector>()
            .TryAddSingleton <ICompiledModelCodeGenerator, CSharpRuntimeModelCodeGenerator>()
            .TryAddSingleton <ICompiledModelCodeGeneratorSelector, CompiledModelCodeGeneratorSelector>()
            .TryAddSingleton <ICompiledModelScaffolder, CompiledModelScaffolder>()
            .TryAddSingleton <IDesignTimeConnectionStringResolver>(
                new DesignTimeConnectionStringResolver(applicationServiceProviderAccessor))
            .TryAddSingleton <IPluralizer, HumanizerPluralizer>()
            .TryAddSingleton <IScaffoldingModelFactory, RelationalScaffoldingModelFactory>()
            .TryAddSingleton <IScaffoldingTypeMapper, ScaffoldingTypeMapper>()
            .TryAddSingleton <MigrationsCodeGeneratorDependencies, MigrationsCodeGeneratorDependencies>()
            .TryAddSingleton <ModelCodeGeneratorDependencies, ModelCodeGeneratorDependencies>()
            .TryAddScoped <IReverseEngineerScaffolder, ReverseEngineerScaffolder>()
            .TryAddScoped <MigrationsScaffolderDependencies, MigrationsScaffolderDependencies>()
            .TryAddScoped <IMigrationsScaffolder, MigrationsScaffolder>()
            .TryAddScoped <ISnapshotModelProcessor, SnapshotModelProcessor>());

        var loggerFactory = new LoggerFactory(
            new[] { new OperationLoggerProvider(reporter) }, new LoggerFilterOptions {
            MinLevel = LogLevel.Debug
        });

        services.AddScoped <ILoggerFactory>(_ => loggerFactory);

        return(services);
    }
Пример #12
0
        private DbContextOperations GetOperations(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            var reporter = new OperationReporter(new OperationReportHandler());

            return(new DbContextOperations(reporter, assembly, assembly, Array.Empty <string>()));
        }
Пример #13
0
        public static IServiceCollection AddSqlServerDacpacStoredProcedureDesignTimeServices(
            this IServiceCollection services,
            IOperationReporter reporter = null)
        {
            if (reporter == null)
            {
                reporter = new OperationReporter(handler: null);
            }

            return(services
                   .AddSingleton <IProcedureModelFactory, SqlServerDacpacStoredProcedureModelFactory>()
                   .AddSingleton <IProcedureScaffolder, SqlServerStoredProcedureScaffolder>()
                   .AddLogging(b => b.SetMinimumLevel(LogLevel.Debug).AddProvider(new OperationLoggerProvider(reporter))));
        }
        private DesignTimeServicesBuilder GetDesignTimeServicesBuilder(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            var reporter = new OperationReporter(
                new OperationReportHandler());

            return(new DesignTimeServicesBuilder(assembly, assembly, reporter, Array.Empty <string>()));
        }
Пример #15
0
        private DesignTimeServicesBuilder GetDesignTimeServicesBuilder(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            //TODO Use OperationHandler output!!
            var reporter = new OperationReporter(
                new OperationReportHandler());

            var builder = new DesignTimeServicesBuilder(assembly, reporter);

            return(builder);
        }
        private DbContextOperations GetOperations(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            //TODO Use OperationHandler output!!
            var reporter = new OperationReporter(
                new OperationReportHandler());

            var operations = new DbContextOperations(reporter, assembly, assembly);

            return(operations);
        }
        private static void AddMigrations(ApplicationDbContext context)
        {
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => Console.WriteLine("  error: " + m),
                    m => Console.WriteLine("   warn: " + m),
                    m => Console.WriteLine("   info: " + m),
                    m => Console.WriteLine("verbose: " + m)));

            var designTimeServices = new ServiceCollection()
                                     .AddSingleton(context.GetService <IHistoryRepository>())
                                     .AddSingleton(context.GetService <IMigrationsIdGenerator>())
                                     .AddSingleton(context.GetService <IMigrationsModelDiffer>())
                                     .AddSingleton(context.GetService <IMigrationsAssembly>())
                                     .AddSingleton(context.Model)
                                     .AddSingleton(context.GetService <ICurrentDbContext>())
                                     .AddSingleton(context.GetService <IDatabaseProvider>())
                                     .AddSingleton <MigrationsCodeGeneratorDependencies>()
                                     .AddSingleton <ICSharpHelper, CSharpHelper>()
                                     .AddSingleton <CSharpMigrationOperationGeneratorDependencies>()
                                     .AddSingleton <ICSharpMigrationOperationGenerator, CSharpMigrationOperationGenerator>()
                                     .AddSingleton <CSharpSnapshotGeneratorDependencies>()
                                     .AddSingleton <ICSharpSnapshotGenerator, CSharpSnapshotGenerator>()
                                     .AddSingleton <CSharpMigrationsGeneratorDependencies>()
                                     .AddSingleton <IMigrationsCodeGenerator, CSharpMigrationsGenerator>()
                                     .AddSingleton <IOperationReporter>(reporter)
                                     .AddSingleton <MigrationsScaffolderDependencies>()
                                     .AddSingleton <MigrationsScaffolder>()
                                     .BuildServiceProvider();

            var scaffolder = designTimeServices.GetRequiredService <MigrationsScaffolder>();

            var migration = scaffolder.ScaffoldMigration(
                "MyMigration",
                "AspNetCoreJwtAuthentication.Data");

            File.WriteAllText(
                migration.MigrationId + migration.FileExtension,
                migration.MigrationCode);
            File.WriteAllText(
                migration.MigrationId + ".Designer" + migration.FileExtension,
                migration.MetadataCode);
            File.WriteAllText(migration.SnapshotName + migration.FileExtension,
                              migration.SnapshotCode);
        }
Пример #18
0
        private DbContextOperations GetOperations(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            //TODO Use OperationHandler output!!
            var reporter = new OperationReporter(new OperationReportHandler());

#if CORE21 || CORE22
            return(new DbContextOperations(reporter, assembly, assembly, Array.Empty <string>()));
#else
            return(new DbContextOperations(reporter, assembly, assembly));
#endif
        }
Пример #19
0
        private static ScaffoldedMigration ScaffoldMigration(ITestOutputHelper output, string migrationName)
        {
            var reporter = new OperationReporter(
                new OperationReportHandler(
                    m => output.WriteLine($"  error: {m}"),
                    m => output.WriteLine($"   warn: {m}"),
                    m => output.WriteLine($"   info: {m}"),
                    m => output.WriteLine($"verbose: {m}")));

            var assembly = System.Reflection.Assembly.GetExecutingAssembly();

            using var context = NodaTimeContext.Create();

            return(new DesignTimeServicesBuilder(assembly, assembly, reporter, Array.Empty <string>())
                   .Build(context)
                   .GetRequiredService <IMigrationsScaffolder>()
                   .ScaffoldMigration(migrationName, "Microsoft.EntityFrameworkCore.Sqlite"));
        }
Пример #20
0
        /// <summary>
        ///     <para>Initializes a new instance of the <see cref="OperationExecutor" /> class.</para>
        ///     <para>The arguments supported by <paramref name="args" /> are:</para>
        ///     <para><c>targetName</c>--The assembly name of the target project.</para>
        ///     <para><c>startupTargetName</c>--The assembly name of the startup project.</para>
        ///     <para><c>projectDir</c>--The target project's root directory.</para>
        ///     <para><c>rootNamespace</c>--The target project's root namespace.</para>
        ///     <para><c>language</c>--The programming language to be used to generate classes.</para>
        ///     <para><c>remainingArguments</c>--Extra arguments passed into the operation.</para>
        /// </summary>
        /// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
        /// <param name="args"> The executor arguments. </param>
        public OperationExecutor(IOperationReportHandler reportHandler, IDictionary args)
        {
            Check.NotNull(reportHandler, nameof(reportHandler));
            Check.NotNull(args, nameof(args));

            _reporter          = new OperationReporter(reportHandler);
            _targetName        = (string)args["targetName"] !;
            _startupTargetName = (string)args["startupTargetName"] !;
            _projectDir        = (string)args["projectDir"] !;
            _rootNamespace     = (string?)args["rootNamespace"];
            _language          = (string?)args["language"];
            _designArgs        = (string[]?)args["remainingArguments"];

            var toolsVersion   = (string?)args["toolsVersion"];
            var runtimeVersion = ProductInfo.GetVersion();

            if (toolsVersion != null &&
                new SemanticVersionComparer().Compare(toolsVersion, runtimeVersion) < 0)
            {
                _reporter.WriteWarning(DesignStrings.VersionMismatch(toolsVersion, runtimeVersion));
            }
        }
Пример #21
0
        private DesignTimeServicesBuilder GetDesignTimeServicesBuilder(string outputPath)
        {
            var assembly = Load(outputPath);

            if (assembly == null)
            {
                throw new ArgumentException("Unable to load project assembly");
            }

            //TODO Use OperationHandler output!!
            var reporter = new OperationReporter(
                new OperationReportHandler());

#if CORE21
            return(new DesignTimeServicesBuilder(assembly, reporter, Array.Empty <string>()));
#else
#if CORE22
            return(new DesignTimeServicesBuilder(assembly, assembly, reporter, Array.Empty <string>()));
#else
            return(new DesignTimeServicesBuilder(assembly, reporter));
#endif
#endif
        }
Пример #22
0
        private DbContext TryCreateContextUsingAppCode(Type dbContextType, Type startupType)
        {
            try
            {
                // Use EF design APIs to get the DBContext instance.
                var operationHandler  = new OperationReportHandler();
                var operationReporter = new OperationReporter(operationHandler);
                // EF infers the environment (Development/ Production) based on the environment variable
                // ASPNETCORE_ENVIRONMENT. This should already be set up by the CodeGeneration.Design process.
                var dbContextOperations = new DbContextOperations(
                    operationReporter,
                    dbContextType.GetTypeInfo().Assembly,
                    startupType.GetTypeInfo().Assembly);

                var dbContextService = dbContextOperations.CreateContext(dbContextType.FullName);

                return(dbContextService);
            }
            catch (Exception ex)
            {
                throw ex.Unwrap(_logger);
            }
        }
Пример #23
0
        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>();

            //TODO await update to 2.1
            //if (reverseEngineerOptions.UseHandleBars)
            //{
            //    serviceCollection.AddHandlebarsScaffolding(reverseEngineerOptions.ProjectPath);
            //}

            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.Npgsql:
                var npgsqlProvider = new NpgsqlDesignTimeServices();
                npgsqlProvider.ConfigureDesignTimeServices(serviceCollection);
                break;

            case DatabaseType.SQLServer:
                var provider = new SqlServerDesignTimeServices();
                provider.ConfigureDesignTimeServices(serviceCollection);
                if (!string.IsNullOrEmpty(reverseEngineerOptions.Dacpac))
                {
                    serviceCollection.AddSingleton <IDatabaseModelFactory, SqlServerDacpacDatabaseModelFactory>();
                }
                break;

            case DatabaseType.SQLite:
                var sqliteProvider = new SqliteDesignTimeServices();
                sqliteProvider.ConfigureDesignTimeServices(serviceCollection);
                serviceCollection.AddSingleton <IDatabaseModelFactory, CustomSqliteDatabaseModelFactory>();
                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;

            var subNamespace = SubnamespaceFromOutputPath(reverseEngineerOptions.ProjectPath, reverseEngineerOptions.OutputPath);

            if (!string.IsNullOrEmpty(subNamespace))
            {
                @namespace += "." + subNamespace;
            }

            var scaffoldedModel = scaffolder.ScaffoldModel(
                reverseEngineerOptions.Dacpac != null
                        ? reverseEngineerOptions.Dacpac
                        : reverseEngineerOptions.ConnectionString,
                reverseEngineerOptions.Tables,
                schemas,
                @namespace,
                "C#",
                null,
                reverseEngineerOptions.ContextClassName,
                !reverseEngineerOptions.UseFluentApiOnly,
                useDatabaseNames: reverseEngineerOptions.UseDatabaseNames);

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

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

            PostProcessContext(filePaths.ContextFile, reverseEngineerOptions);

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

            return(result);
        }
Пример #24
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);
        }
        /// <summary>
        ///     <para>Initializes a new instance of the <see cref="OperationExecutor" /> class.</para>
        ///     <para>The arguments supported by <paramref name="args" /> are:</para>
        ///     <para><c>targetName</c>--The assembly name of the target project.</para>
        ///     <para><c>startupTargetName</c>--The assembly name of the startup project.</para>
        ///     <para><c>projectDir</c>--The target project's root directory.</para>
        ///     <para><c>rootNamespace</c>--The target project's root namespace.</para>
        /// </summary>
        /// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
        /// <param name="args"> The executor arguments. </param>
        public OperationExecutor([NotNull] object reportHandler, [NotNull] IDictionary args)
        {
            Check.NotNull(reportHandler, nameof(reportHandler));
            Check.NotNull(args, nameof(args));

            var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(reportHandler);
            var reporter = new OperationReporter(unwrappedReportHandler);

            var targetName        = (string)args["targetName"];
            var startupTargetName = (string)args["startupTargetName"];

            _projectDir = (string)args["projectDir"];
            var rootNamespace = (string)args["rootNamespace"];
            var language      = (string)args["language"];
            var toolsVersion  = (string)args["toolsVersion"];

            // TODO: Flow in from tools (issue #8332)
            var designArgs = Array.Empty <string>();

            var runtimeVersion = ProductInfo.GetVersion();

            if (toolsVersion != null &&
                new SemanticVersionComparer().Compare(RemovePatch(toolsVersion), RemovePatch(runtimeVersion)) < 0)
            {
                reporter.WriteWarning(DesignStrings.VersionMismatch(toolsVersion, runtimeVersion));
            }

            // NOTE: LazyRef is used so any exceptions get passed to the resultHandler
            var startupAssembly = new LazyRef <Assembly>(
                () => Assembly.Load(new AssemblyName(startupTargetName)));
            var assembly = new LazyRef <Assembly>(
                () =>
            {
                try
                {
                    return(Assembly.Load(new AssemblyName(targetName)));
                }
                catch (Exception ex)
                {
                    throw new OperationException(
                        DesignStrings.UnreferencedAssembly(targetName, startupTargetName),
                        ex);
                }
            });

            _contextOperations = new LazyRef <DbContextOperations>(
                () => new DbContextOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    designArgs));
            _databaseOperations = new LazyRef <DatabaseOperations>(
                () => new DatabaseOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    _projectDir,
                    rootNamespace,
                    language,
                    designArgs));
            _migrationsOperations = new LazyRef <MigrationsOperations>(
                () => new MigrationsOperations(
                    reporter,
                    assembly.Value,
                    startupAssembly.Value,
                    _projectDir,
                    rootNamespace,
                    language,
                    designArgs));

            string RemovePatch(string versionString)
            {
                var prereleaseIndex = versionString.IndexOf("-", StringComparison.Ordinal);

                if (prereleaseIndex != -1)
                {
                    versionString = versionString.Substring(0, prereleaseIndex);
                }

                var version = new Version(versionString);

                return(new Version(version.Major, version.Minor).ToString());
            }
        }
        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;
        }
Пример #27
0
        public static ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions options)
        {
            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(options);
            var scaffolder      = serviceProvider.GetService <IReverseEngineerScaffolder>();
            var schemas         = new List <string>();

            options.ConnectionString = SqlServerHelper.SetConnectionString(options.DatabaseType, options.ConnectionString);

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

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

            if (options.UseNoObjectFilter)
            {
                options.Tables = new List <SerializationTableModel>();
            }

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

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

            var modelNamespace   = string.Empty;
            var contextNamespace = string.Empty;

            if (string.IsNullOrEmpty(options.ProjectRootNamespace))
            {
                modelNamespace = !string.IsNullOrEmpty(options.ModelNamespace)
                    ? options.ModelNamespace
                    : PathHelper.GetNamespaceFromOutputPath(outputDir, options.ProjectPath, options.ProjectRootNamespace);

                contextNamespace = !string.IsNullOrEmpty(options.ContextNamespace)
                    ? options.ContextNamespace
                    : PathHelper.GetNamespaceFromOutputPath(outputContextDir, options.ProjectPath, options.ProjectRootNamespace);
            }
            else
            {
                modelNamespace = !string.IsNullOrEmpty(options.ModelNamespace)
                    ? options.ProjectRootNamespace + "." + options.ModelNamespace
                    : PathHelper.GetNamespaceFromOutputPath(outputDir, options.ProjectPath, options.ProjectRootNamespace);

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

            var             entityTypeConfigurationPaths = new List <string>();
            SavedModelFiles procedurePaths = null;
            SavedModelFiles functionPaths  = null;

            SavedModelFiles filePaths = ReverseEngineerScaffolder.GenerateDbContext(options, serviceProvider, schemas, outputContextDir, modelNamespace, contextNamespace);

            if (options.SelectedToBeGenerated != 2)
            {
                procedurePaths = ReverseEngineerScaffolder.GenerateStoredProcedures(options, ref errors, serviceProvider, outputContextDir, modelNamespace, contextNamespace);

                functionPaths = ReverseEngineerScaffolder.GenerateFunctions(options, ref errors, serviceProvider, outputContextDir, modelNamespace, contextNamespace);
#if CORE50
#else
                RemoveOnConfiguring(filePaths.ContextFile, options.IncludeConnectionString);
#endif
                PostProcess(filePaths.ContextFile);

                entityTypeConfigurationPaths = SplitDbContext(filePaths.ContextFile, options.UseDbContextSplitting, contextNamespace, options.UseNullableReferences);
            }
            else if (options.SelectedToBeGenerated == 2 &&
                     (options.Tables.Count(t => t.ObjectType == ObjectType.Procedure) > 0 ||
                      options.Tables.Count(t => t.ObjectType == ObjectType.ScalarFunction) > 0))
            {
                warnings.Add("Selected stored procedures/scalar functions will not be generated, as 'Entity Types only' was selected");
            }

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

            var cleanUpPaths = CreateCleanupPaths(procedurePaths, functionPaths, filePaths);

            CleanUp(cleanUpPaths, entityTypeConfigurationPaths);

            var allfiles = filePaths.AdditionalFiles.ToList();
            if (procedurePaths != null)
            {
                allfiles.AddRange(procedurePaths.AdditionalFiles);
                allfiles.Add(procedurePaths.ContextFile);
            }
            if (functionPaths != null)
            {
                allfiles.AddRange(functionPaths.AdditionalFiles);
                allfiles.Add(functionPaths.ContextFile);
            }

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

            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)));

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

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

            if (reverseEngineerOptions.UseHandleBars)
            {
                serviceCollection.AddHandlebarsScaffolding(reverseEngineerOptions.ProjectPath);
            }

            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);
                break;

            case DatabaseType.SQLite:
                var sqliteProvider = new SqliteDesignTimeServices();
                sqliteProvider.ConfigureDesignTimeServices(serviceCollection);
                serviceCollection.AddSingleton <IDatabaseModelFactory, CustomSqliteDatabaseModelFactory>();
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var serviceProvider = serviceCollection.BuildServiceProvider();
            var generator       = serviceProvider.GetService <IModelScaffolder>();

            var filePaths = generator.Generate(
                reverseEngineerOptions.ConnectionString,
                reverseEngineerOptions.Tables,
                new List <string>(),
                reverseEngineerOptions.ProjectPath,
                reverseEngineerOptions.OutputPath,
                reverseEngineerOptions.ProjectRootNamespace,
                reverseEngineerOptions.ContextClassName,
                !reverseEngineerOptions.UseFluentApiOnly,
                overwriteFiles: true,
                useDatabaseNames: reverseEngineerOptions.UseDatabaseNames);

            // Explanation: Use table and column names directly from the database.

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

            if (!reverseEngineerOptions.IncludeConnectionString)
            {
                PostProcessContext(filePaths.ContextFile);
            }

            var result = new EfCoreReverseEngineerResult
            {
                EntityErrors        = errors,
                EntityWarnings      = warnings,
                EntityTypeFilePaths = filePaths.EntityTypeFiles,
                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)));

            // 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);
        }
Пример #30
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);
        }