示例#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));
        }
示例#2
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);
        }
示例#3
0
 protected void Test(
     Action <ModelBuilder> buildModel,
     ModelCodeGenerationOptions options,
     Action <ScaffoldedModel> assertScaffold)
 {
     Test(buildModel, options, assertScaffold, null);
 }
        public override ScaffoldedModel GenerateModel(IModel model,
                                                      string @namespace,
                                                      string contextDir,
                                                      string contextName,
                                                      string connectionString,
                                                      ModelCodeGenerationOptions options)
        {
            EntityTypeConfigurationTemplateService.RegisterPartialTemplates();

            var resultingFiles = base.GenerateModel(model, @namespace, contextDir, contextName, connectionString, options);

            string generatedCode;

            if (!(CSharpEntityTypeConfigurationGenerator is NullCSharpEntityTypeConfigurationGenerator))
            {
                foreach (var entityType in model.GetEntityTypes())
                {
                    generatedCode = CSharpEntityTypeConfigurationGenerator.WriteCode(entityType, @namespace, options.UseDataAnnotations);

                    var transformedFileName   = EntityTypeTransformationService.TransformEntityTypeConfigurationFileName(entityType.DisplayName(), HandlebarsScaffoldingOptions.EntityTypeConfigurationFileNameSuffix);
                    var entityTypeCfgFileName = transformedFileName + FileExtension;
                    resultingFiles.AdditionalFiles.Add(new ScaffoldedFile {
                        Path = Path.Combine(contextDir, contextName + HandlebarsScaffoldingOptions.EntityTypeConfigurationDirSuffix, entityTypeCfgFileName), Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }
示例#5
0
    protected void Test(
        Action <ModelBuilder> buildModel,
        ModelCodeGenerationOptions options,
        Action <ScaffoldedModel> assertScaffold)
    {
        var designServices = new ServiceCollection();

        AddModelServices(designServices);

        var modelBuilder = SqlServerTestHelpers.Instance.CreateConventionBuilder(customServices: designServices);

        modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion);
        buildModel(modelBuilder);

        var model = modelBuilder.FinalizeModel(designTime: true, skipValidation: true);

        var services = CreateServices();

        AddScaffoldingServices(services);

        var generator = services.BuildServiceProvider(validateScopes: true)
                        .GetRequiredService <IModelCodeGenerator>();

        options.ModelNamespace ??= "TestNamespace";
        options.ContextName      = "TestDbContext";
        options.ConnectionString = "Initial Catalog=TestDatabase";

        var scaffoldedModel = generator.GenerateModel(
            model,
            options);

        assertScaffold(scaffoldedModel);
    }
        /// <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));
        }
示例#7
0
        protected void Test(
            Action <ModelBuilder> buildModel,
            ModelCodeGenerationOptions options,
            Action <ScaffoldedModel> assertScaffold,
            Action <IModel> assertModel)
        {
            var modelBuilder = SqlServerTestHelpers.Instance.CreateConventionBuilder();

            modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion);
            buildModel(modelBuilder);

            var model = modelBuilder.FinalizeModel();

            var services = new ServiceCollection()
                           .AddEntityFrameworkDesignTimeServices();

            new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services);

            var generator = services
                            .BuildServiceProvider()
                            .GetRequiredService <IModelCodeGenerator>();

            options.ModelNamespace ??= "TestNamespace";
            options.ContextName      = "TestDbContext";
            options.ConnectionString = "Initial Catalog=TestDatabase";

            var scaffoldedModel = generator.GenerateModel(
                model,
                options);

            assertScaffold(scaffoldedModel);

            var build = new BuildSource
            {
                References =
                {
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Abstractions"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer")
                },
                Sources = new List <string>(
                    new[] { scaffoldedModel.ContextFile.Code }.Concat(
                        scaffoldedModel.AdditionalFiles.Select(f => f.Code)))
            };

            var assembly         = build.BuildInMemory();
            var contextNamespace = options.ContextNamespace ?? options.ModelNamespace;
            var context          = (DbContext)assembly.CreateInstance(
                !string.IsNullOrEmpty(contextNamespace)
                    ? contextNamespace + "." + options.ContextName
                    : options.ContextName);

            if (assertModel != null)
            {
                var compiledModel = context.Model;
                assertModel(compiledModel);
            }
        }
示例#8
0
        public override ScaffoldedModel GenerateModel(
            IModel model,
            ModelCodeGenerationOptions options)
        {
            Check.NotNull(model, nameof(model));
            Check.NotNull(options, nameof(options));

            if (options.ContextName == null)
            {
                throw new ArgumentException(CoreStrings.ArgumentPropertyNull(nameof(options.ContextName), nameof(options)), nameof(options));
            }

            if (options.ConnectionString == null)
            {
                throw new ArgumentException(CoreStrings.ArgumentPropertyNull(nameof(options.ConnectionString), nameof(options)), nameof(options));
            }

            if (options.ModelNamespace == null)
            {
                throw new ArgumentException(CoreStrings.ArgumentPropertyNull(nameof(options.ModelNamespace), nameof(options)), nameof(options));
            }

            var generatedCode = CSharpDbContextGenerator.WriteCode(
                model,
                options.ContextName,
                options.ConnectionString,
                options.ContextNamespace,
                options.ModelNamespace,
                options.UseDataAnnotations,
                options.SuppressConnectionStringWarning,
                options.SuppressOnConfiguring);

            // output DbContext .cs file
            var dbContextFileName = options.ContextName + FileExtension;
            var resultingFiles    = new ScaffoldedModel
            {
                ContextFile = new ScaffoldedFile
                {
                    Path = options.ContextDir != null
                        ? Path.Combine(options.ContextDir, dbContextFileName)
                        : dbContextFileName,
                    Code = generatedCode
                }
            };

            foreach (var entityType in model.GetEntityTypes())
            {
                generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, options.ModelNamespace, options.UseDataAnnotations);

                // output EntityType poco .cs file
                var entityTypeFileName = entityType.DisplayName() + FileExtension;
                resultingFiles.AdditionalFiles.Add(
                    new ScaffoldedFile {
                    Path = entityTypeFileName, Code = generatedCode
                });
            }

            return(resultingFiles);
        }
示例#9
0
        /// <summary>
        /// <summary>Generates code for a model.</summary>
        /// </summary>
        /// <param name="model"> The model.</param>
        /// <param name="options"> The options to use during generation. </param>
        /// <returns> The generated model. </returns>
        public override ScaffoldedModel GenerateModel(IModel model, ModelCodeGenerationOptions options)
        {
            Check.NotNull(model, nameof(model));
            Check.NotNull(options, nameof(options));

            // Register Hbs helpers and partial templates
            HandlebarsHelperService.RegisterHelpers();
            HandlebarsBlockHelperService.RegisterBlockHelpers();
            DbContextTemplateService.RegisterPartialTemplates();
            EntityTypeTemplateService.RegisterPartialTemplates();

            var resultingFiles = new ScaffoldedModel();

            string generatedCode;

            if (!(CSharpDbContextGenerator is NullCSharpDbContextGenerator))
            {
                generatedCode = CSharpDbContextGenerator.WriteCode(
                    model,
                    options.ContextName,
                    options.ConnectionString,
                    options.ContextNamespace,
                    options.ModelNamespace,
                    options.UseDataAnnotations,
                    options.SuppressConnectionStringWarning);

                var dbContextFileName = options.ContextName + FileExtension;
                resultingFiles.ContextFile = new ScaffoldedFile
                {
                    Path = options.ContextDir != null
                        ? Path.Combine(options.ContextDir, dbContextFileName)
                        : dbContextFileName,
                    Code = generatedCode
                };
            }

            if (!(CSharpEntityTypeGenerator is NullCSharpEntityTypeGenerator))
            {
                foreach (var entityType in model.GetScaffoldEntityTypes(_options.Value))
                {
                    generatedCode = CSharpEntityTypeGenerator.WriteCode(
                        entityType,
                        options.ModelNamespace,
                        options.UseDataAnnotations);

                    var transformedFileName = EntityTypeTransformationService.TransformEntityFileName(entityType.DisplayName());
                    var entityTypeFileName  = transformedFileName + FileExtension;
                    resultingFiles.AdditionalFiles.Add(
                        new ScaffoldedFile
                    {
                        Path = entityTypeFileName,
                        Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }
示例#10
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);
        }
示例#11
0
        protected void Test(
            Action <ModelBuilder> buildModel,
            ModelCodeGenerationOptions options,
            Action <ScaffoldedModel> assertScaffold,
            Action <IModel> assertModel)
        {
            var modelBuilder = new ModelBuilder(BuildNonValidatingConventionSet());

            modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersionAnnotation);
            buildModel(modelBuilder);
            var _ = modelBuilder.Model.Scaffolding().EntityTypeErrors;

            var model = modelBuilder.FinalizeModel();

            var services = new ServiceCollection()
                           .AddEntityFrameworkDesignTimeServices();

            new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services);

            var generator = services
                            .BuildServiceProvider()
                            .GetRequiredService <IModelCodeGenerator>();

            var scaffoldedModel = generator.GenerateModel(
                model,
                "TestNamespace",
                "TestNamespace",
                "TestNamespace",
                /*contextDir:*/ string.Empty,
                "TestDbContext",
                "Initial Catalog=TestDatabase",
                options);

            assertScaffold(scaffoldedModel);

            var build = new BuildSource
            {
                References =
                {
                    BuildReference.ByName("Microsoft.EntityFrameworkCore"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer")
                },
                Sources = new List <string>(
                    new[] { scaffoldedModel.ContextFile.Code }.Concat(
                        scaffoldedModel.AdditionalFiles.Select(f => f.Code)))
            };

            var assembly      = build.BuildInMemory();
            var context       = (DbContext)assembly.CreateInstance("TestNamespace.TestDbContext");
            var compiledModel = context.Model;

            assertModel(compiledModel);
        }
示例#12
0
        private void Test(
            Action <ModelBuilder> buildModel,
            ModelCodeGenerationOptions options,
            Action <ScaffoldedModel> assertScaffold,
            Action <IModel> assertModel)
        {
            var modelBuilder = new ModelBuilder(SqlServerConventionSetBuilder.Build());

            buildModel(modelBuilder);
            modelBuilder.GetInfrastructure().Metadata.Validate();

            var model = modelBuilder.Model;

            var services = new ServiceCollection()
                           .AddEntityFrameworkDesignTimeServices();

            new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services);

            var generator = services
                            .BuildServiceProvider()
                            .GetRequiredService <IModelCodeGenerator>();

            var scaffoldedModel = generator.GenerateModel(
                model,
                "TestNamespace",
                /*contextDir:*/ string.Empty,
                "TestDbContext",
                "Initial Catalog=TestDatabase",
                options);

            assertScaffold(scaffoldedModel);

            var build = new BuildSource
            {
                References =
                {
                    BuildReference.ByName("Microsoft.EntityFrameworkCore"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer")
                },
                Sources = new List <string>(
                    Enumerable.Concat(
                        new[] { scaffoldedModel.ContextFile.Code },
                        scaffoldedModel.AdditionalFiles.Select(f => f.Code)))
            };

            var assembly      = build.BuildInMemory();
            var context       = (DbContext)assembly.CreateInstance("TestNamespace.TestDbContext");
            var compiledModel = context.Model;

            assertModel(compiledModel);
        }
示例#13
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));
        }
        public void ModelSameNamespaceDbContext_works()
        {
            var modelGenerationOptions = new ModelCodeGenerationOptions {
                ContextNamespace = "TestNamespace"
            };

            const string entityInAnotherNamespaceTypeName = "EntityInAnotherNamespace";

            Test(
                modelBuilder => modelBuilder.Entity(entityInAnotherNamespaceTypeName)
                , modelGenerationOptions
                , code => Assert.DoesNotContain(string.Concat("using ", modelGenerationOptions.ModelNamespace, ";"), code.ContextFile.Code)
                , model => Assert.NotNull(model.FindEntityType(string.Concat(modelGenerationOptions.ModelNamespace, ".", entityInAnotherNamespaceTypeName)))
                );
        }
        /// <summary>
        ///     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.
        /// </summary>
        public override ScaffoldedModel GenerateModel(
            IModel model,
            string rootNamespace,
            string modelNamespace,
            string contextNamespace,
            string contextDir,
            string contextName,
            string connectionString,
            ModelCodeGenerationOptions options)
        {
            Check.NotNull(model, nameof(model));
            Check.NotEmpty(modelNamespace, nameof(modelNamespace));
            Check.NotEmpty(contextNamespace, nameof(contextNamespace));
            Check.NotNull(contextDir, nameof(contextDir));
            Check.NotEmpty(contextName, nameof(contextName));
            Check.NotEmpty(connectionString, nameof(connectionString));
            Check.NotNull(options, nameof(options));

            var resultingFiles = new ScaffoldedModel();

            var generatedCode = CSharpDbContextGenerator.WriteCode(model, contextNamespace, contextName, connectionString, options.UseDataAnnotations, options.SuppressConnectionStringWarning);

            // output DbContext .cs file
            var dbContextFileName = contextName + FileExtension;

            resultingFiles.ContextFile = new ScaffoldedFile
            {
                Path = Path.Combine(contextDir, dbContextFileName),
                Code = generatedCode
            };

            foreach (var entityType in model.GetEntityTypes())
            {
                generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, modelNamespace, options.UseDataAnnotations);

                // output EntityType poco .cs file
                var entityTypeFileName = ((ITypeBase)entityType).DisplayName() + FileExtension;
                resultingFiles.AdditionalFiles.Add(
                    new ScaffoldedFile
                {
                    Path = entityTypeFileName,
                    Code = generatedCode
                });
            }

            return(resultingFiles);
        }
    public void Select_throws_when_no_service_for_language()
    {
        var selector = new ModelCodeGeneratorSelector(
            new[]
        {
            new TestModelCodeGenerator("C#")
        });
        var options = new ModelCodeGenerationOptions
        {
            Language = "VB"
        };

        var ex = Assert.Throws <OperationException>(
            () => selector.Select(options));

        Assert.Equal(DesignStrings.NoLanguageService("VB", nameof(IModelCodeGenerator)), ex.Message);
    }
示例#17
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));
        }
 //
 // 摘要:
 //     /// 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));
 }
        /// <summary>
        /// Generates code for a model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="options">The model generatation options <see cref="ModelCodeGenerationOptions"/>.</param>
        /// <returns></returns>
        public ScaffoldedModel GenerateModel(IModel model, ModelCodeGenerationOptions options)
        {
            var files = new ScaffoldedModel();

            var contextCode = this.dbContextGenerator.WriteCode(
                model,
                options.ContextNamespace,
                options.ContextName,
                options.ConnectionString,
                options.UseDataAnnotations,
                options.SuppressConnectionStringWarning
                );

            files.ContextFile = new ScaffoldedFile
            {
                Path = Path.Combine(options.ContextDir, options.ContextName + FileExtension),
                Code = contextCode
            };

            foreach (var entityType in model.GetEntityTypes())
            {
                var entityCode = this.entityTypeGenerator.WriteCode(
                    entityType,
                    options.ContextNamespace,
                    options.UseDataAnnotations
                    );

                var entityFile = new ScaffoldedFile
                {
                    Path = entityType.DisplayName() + FileExtension,
                    Code = entityCode
                };

                files.AdditionalFiles.Add(entityFile);
            }

            return(files);
        }
        public override ScaffoldedModel GenerateModel(IModel model, ModelCodeGenerationOptions options)
        {
            var resultingFiles = new ScaffoldedModel();

            var contextGenerator = new MyDbContextGenerator
            {
                Session = new Dictionary <string, object>
                {
                    ["Model"]            = model,
                    ["ModelNamespace"]   = options.ModelNamespace,
                    ["Namespace"]        = options.ContextNamespace,
                    ["ContextName"]      = options.ContextName,
                    ["ConnectionString"] = options.ConnectionString,
                    ["SuppressConnectionStringWarning"] = options.SuppressConnectionStringWarning,
                    ["UseDataAnnotations"] = options.UseDataAnnotations,

                    ["Code"]           = _csharpHelper,
                    ["ProviderCode"]   = _providerConfigurationCodeGenerator,
                    ["AnnotationCode"] = _annotationCodeGenerator
                }
            };

            contextGenerator.Initialize();
            var generatedCode = contextGenerator.TransformText();

            var dbContextFileName = options.ContextName + ".cs";

            resultingFiles.ContextFile = new ScaffoldedFile
            {
                Path = Path.Combine(options.ContextDir, dbContextFileName),
                Code = generatedCode
            };

            foreach (var entityType in model.GetEntityTypes())
            {
                var entityGenerator = new MyEntityTypeGenerator
                {
                    Session = new Dictionary <string, object>
                    {
                        ["EntityType"]         = entityType,
                        ["Namespace"]          = options.ModelNamespace,
                        ["UseDataAnnotations"] = options.UseDataAnnotations,

                        ["Code"] = _csharpHelper
                    }
                };
                entityGenerator.Initialize();
                generatedCode = entityGenerator.TransformText();

                resultingFiles.AdditionalFiles.Add(
                    new ScaffoldedFile
                {
                    Path = entityType.Name + ".cs",
                    Code = generatedCode
                });

                var configurationGenerator = new MyEntityTypeConfigurationGenerator
                {
                    Session = new Dictionary <string, object>
                    {
                        ["EntityType"]         = entityType,
                        ["ModelNamespace"]     = options.ModelNamespace,
                        ["Namespace"]          = options.ContextNamespace,
                        ["UseDataAnnotations"] = options.UseDataAnnotations,

                        ["Code"]           = _csharpHelper,
                        ["AnnotationCode"] = _annotationCodeGenerator
                    }
                };
                configurationGenerator.Initialize();
                generatedCode = configurationGenerator.TransformText();

                resultingFiles.AdditionalFiles.Add(
                    new ScaffoldedFile
                {
                    Path = Path.Combine(options.ContextDir, entityType.Name + "Configuration.cs"),
                    Code = generatedCode
                });
            }

            return(resultingFiles);
        }
        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;
        }
        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);
        }
示例#23
0
        protected void Test(
            Action <ModelBuilder> buildModel,
            ModelCodeGenerationOptions options,
            Action <ScaffoldedModel> assertScaffold,
            Action <IModel> assertModel,
            bool skipBuild = false)
        {
            var designServices = new ServiceCollection();

            AddModelServices(designServices);

            var modelBuilder = SqlServerTestHelpers.Instance.CreateConventionBuilder(customServices: designServices);

            modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion);
            buildModel(modelBuilder);

            var model = modelBuilder.FinalizeModel(designTime: true, skipValidation: true);

            var services = CreateServices();

            AddScaffoldingServices(services);

            var generator = services.BuildServiceProvider(validateScopes: true)
                            .GetRequiredService <IModelCodeGenerator>();

            options.ModelNamespace ??= "TestNamespace";
            options.ContextName      = "TestDbContext";
            options.ConnectionString = "Initial Catalog=TestDatabase";

            var scaffoldedModel = generator.GenerateModel(
                model,
                options);

            assertScaffold(scaffoldedModel);

            var build = new BuildSource
            {
                References =
                {
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Abstractions"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational"),
                    BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer")
                },
                Sources = new[] { scaffoldedModel.ContextFile }.Concat(scaffoldedModel.AdditionalFiles)
                .ToDictionary(f => f.Path, f => f.Code),
                NullableReferenceTypes = options.UseNullableReferenceTypes
            };

            if (!skipBuild)
            {
                var assembly = build.BuildInMemory();

                if (assertModel != null)
                {
                    var contextNamespace = options.ContextNamespace ?? options.ModelNamespace;
                    var context          = (DbContext)assembly.CreateInstance(
                        !string.IsNullOrEmpty(contextNamespace)
                            ? contextNamespace + "." + options.ContextName
                            : options.ContextName);

                    var compiledModel = context.GetService <IDesignTimeModel>().Model;
                    assertModel(compiledModel);
                }
            }
        }
示例#24
0
        /// <summary>Generates code for a model.</summary>
        /// <param name="model"> The model. </param>
        /// <param name="namespace"> The namespace. </param>
        /// <param name="contextDir"> The directory of the <see cref="T:Microsoft.EntityFrameworkCore.DbContext" />. </param>
        /// <param name="contextName"> The name of the <see cref="T:Microsoft.EntityFrameworkCore.DbContext" />. </param>
        /// <param name="connectionString"> The connection string. </param>
        /// <param name="options"> The options to use during generation. </param>
        /// <returns> The generated model. </returns>
        public override ScaffoldedModel GenerateModel(IModel model,
                                                      string @namespace,
                                                      string contextDir,
                                                      string contextName,
                                                      string connectionString,
                                                      ModelCodeGenerationOptions options)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            if (string.IsNullOrWhiteSpace(@namespace))
            {
                throw new ArgumentNullException(nameof(@namespace));
            }
            if (contextDir == null)
            {
                throw new ArgumentNullException(nameof(contextDir));
            }
            if (string.IsNullOrWhiteSpace(contextName))
            {
                throw new ArgumentNullException(nameof(contextName));
            }
            if (string.IsNullOrWhiteSpace(connectionString))
            {
                throw new ArgumentNullException(nameof(connectionString));
            }
            if (contextDir == null)
            {
                throw new ArgumentNullException(nameof(contextDir));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // Register Hbs helpers and partial templates
            HandlebarsHelperService.RegisterHelpers();
            DbContextTemplateService.RegisterPartialTemplates();
            EntityTypeTemplateService.RegisterPartialTemplates();

            var resultingFiles = new ScaffoldedModel();

            string generatedCode;

            if (!(CSharpDbContextGenerator is NullCSharpDbContextGenerator))
            {
                generatedCode = CSharpDbContextGenerator.WriteCode(model, @namespace, contextName, connectionString, options.UseDataAnnotations, options.SuppressConnectionStringWarning);

                var dbContextFileName = contextName + FileExtension;
                resultingFiles.ContextFile = new ScaffoldedFile {
                    Path = Path.Combine(contextDir, dbContextFileName), Code = generatedCode
                };
            }

            if (!(CSharpEntityTypeGenerator is NullCSharpEntityTypeGenerator))
            {
                foreach (var entityType in model.GetEntityTypes())
                {
                    generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, @namespace, options.UseDataAnnotations);

                    var transformedFileName = EntityTypeTransformationService.TransformEntityFileName(entityType.DisplayName());
                    var entityTypeFileName  = transformedFileName + FileExtension;
                    resultingFiles.AdditionalFiles.Add(new ScaffoldedFile {
                        Path = entityTypeFileName, Code = generatedCode
                    });
                }
            }

            return(resultingFiles);
        }
    public override ScaffoldedModel GenerateModel(IModel model, ModelCodeGenerationOptions options)
    {
        if (options.ContextName == null)
        {
            throw new ArgumentException(
                      CoreStrings.ArgumentPropertyNull(nameof(options.ContextName), nameof(options)), nameof(options));
        }

        if (options.ConnectionString == null)
        {
            throw new ArgumentException(
                      CoreStrings.ArgumentPropertyNull(nameof(options.ConnectionString), nameof(options)), nameof(options));
        }

        var resultingFiles = new ScaffoldedModel();

        var contextTemplate = Path.Combine(options.ProjectDir !, TemplatesDirectory, "DbContext.t4");

        Check.DebugAssert(_host.Session == null, "Session is not null.");
        _host.Session = _host.CreateSession();
        try
        {
            _host.Session.Add("Model", model);
            _host.Session.Add("Options", options);
            _host.Session.Add("NamespaceHint", options.ContextNamespace ?? options.ModelNamespace);
            _host.Session.Add("ProjectDefaultNamespace", options.RootNamespace);

            var handler       = new TextTemplatingCallback();
            var generatedCode = ProcessTemplate(contextTemplate, handler);

            var dbContextFileName = options.ContextName + handler.Extension;
            resultingFiles.ContextFile = new ScaffoldedFile
            {
                Path = options.ContextDir != null
                    ? Path.Combine(options.ContextDir, dbContextFileName)
                    : dbContextFileName,
                Code = generatedCode
            };
        }
        finally
        {
            _host.Session = null;
        }

        var entityTypeTemplate = Path.Combine(options.ProjectDir !, TemplatesDirectory, "EntityType.t4");

        if (File.Exists(entityTypeTemplate))
        {
            foreach (var entityType in model.GetEntityTypes())
            {
                // TODO: Should this be handled inside the template?
                if (CSharpDbContextGenerator.IsManyToManyJoinEntityType(entityType))
                {
                    continue;
                }

                _host.Session = _host.CreateSession();
                try
                {
                    _host.Session.Add("EntityType", entityType);
                    _host.Session.Add("Options", options);
                    _host.Session.Add("NamespaceHint", options.ModelNamespace);
                    _host.Session.Add("ProjectDefaultNamespace", options.RootNamespace);

                    var handler       = new TextTemplatingCallback();
                    var generatedCode = ProcessTemplate(entityTypeTemplate, handler);
                    if (string.IsNullOrWhiteSpace(generatedCode))
                    {
                        continue;
                    }

                    var entityTypeFileName = entityType.Name + handler.Extension;
                    resultingFiles.AdditionalFiles.Add(
                        new ScaffoldedFile {
                        Path = entityTypeFileName, Code = generatedCode
                    });
                }
                finally
                {
                    _host.Session = null;
                }
            }
        }

        return(resultingFiles);
    }
        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);
        }
示例#27
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();
            }
        }
示例#28
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);
        }
示例#29
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);
        }
示例#30
0
 /// <summary>
 ///     Generates code for a model.
 /// </summary>
 /// <param name="model">The model.</param>
 /// <param name="options">The options to use during generation.</param>
 /// <returns>The generated model.</returns>
 public abstract ScaffoldedModel GenerateModel(
     IModel model,
     ModelCodeGenerationOptions options);