/// <summary> /// Removes the previous migration. /// </summary> /// <param name="projectDir">The project's root directory.</param> /// <param name="rootNamespace">The project's root namespace.</param> /// <param name="force">Don't check to see if the migration has been applied to the database.</param> /// <param name="language">The project's language.</param> /// <returns>The removed migration files.</returns> // TODO: DRY (file names) public virtual MigrationFiles RemoveMigration( string projectDir, string?rootNamespace, bool force, string?language) { var files = new MigrationFiles(); var modelSnapshot = Dependencies.MigrationsAssembly.ModelSnapshot; if (modelSnapshot == null) { throw new OperationException(DesignStrings.NoSnapshot); } var codeGenerator = Dependencies.MigrationsCodeGeneratorSelector.Select(language); IModel?model = null; var migrations = Dependencies.MigrationsAssembly.Migrations .Select(m => Dependencies.MigrationsAssembly.CreateMigration(m.Value, _activeProvider)) .ToList(); if (migrations.Count != 0) { var migration = migrations[migrations.Count - 1]; model = Dependencies.SnapshotModelProcessor.Process(migration.TargetModel); if (!Dependencies.MigrationsModelDiffer.HasDifferences( model.GetRelationalModel(), Dependencies.SnapshotModelProcessor.Process(modelSnapshot.Model).GetRelationalModel())) { var applied = false; try { applied = Dependencies.HistoryRepository.GetAppliedMigrations().Any( e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase)); } catch (Exception ex) when(force) { Dependencies.OperationReporter.WriteVerbose(ex.ToString()); Dependencies.OperationReporter.WriteWarning( DesignStrings.ForceRemoveMigration(migration.GetId(), ex.Message)); } if (applied) { if (force) { Dependencies.Migrator.Migrate( migrations.Count > 1 ? migrations[migrations.Count - 2].GetId() : Migration.InitialDatabase); } else { throw new OperationException(DesignStrings.RevertMigration(migration.GetId())); } } var migrationFileName = migration.GetId() + codeGenerator.FileExtension; var migrationFile = TryGetProjectFile(projectDir, migrationFileName); if (migrationFile != null) { Dependencies.OperationReporter.WriteInformation(DesignStrings.RemovingMigration(migration.GetId())); File.Delete(migrationFile); files.MigrationFile = migrationFile; } else { Dependencies.OperationReporter.WriteWarning( DesignStrings.NoMigrationFile(migrationFileName, migration.GetType().ShortDisplayName())); } var migrationMetadataFileName = migration.GetId() + ".Designer" + codeGenerator.FileExtension; var migrationMetadataFile = TryGetProjectFile(projectDir, migrationMetadataFileName); if (migrationMetadataFile != null) { File.Delete(migrationMetadataFile); files.MetadataFile = migrationMetadataFile; } else { Dependencies.OperationReporter.WriteVerbose( DesignStrings.NoMigrationMetadataFile(migrationMetadataFile)); } model = migrations.Count > 1 ? Dependencies.SnapshotModelProcessor.Process(migrations[migrations.Count - 2].TargetModel) : null; } else { Dependencies.OperationReporter.WriteVerbose(DesignStrings.ManuallyDeleted); } } var modelSnapshotName = modelSnapshot.GetType().Name; var modelSnapshotFileName = modelSnapshotName + codeGenerator.FileExtension; var modelSnapshotFile = TryGetProjectFile(projectDir, modelSnapshotFileName); if (model == null) { if (modelSnapshotFile != null) { Dependencies.OperationReporter.WriteInformation(DesignStrings.RemovingSnapshot); File.Delete(modelSnapshotFile); files.SnapshotFile = modelSnapshotFile; } else { Dependencies.OperationReporter.WriteWarning( DesignStrings.NoSnapshotFile( modelSnapshotFileName, modelSnapshot.GetType().ShortDisplayName())); } } else { var modelSnapshotNamespace = modelSnapshot.GetType().Namespace; Check.DebugAssert(!string.IsNullOrEmpty(modelSnapshotNamespace), "modelSnapshotNamespace is null or empty"); var modelSnapshotCode = codeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, model); if (modelSnapshotFile == null) { modelSnapshotFile = Path.Combine( GetDirectory(projectDir, null, GetSubNamespace(rootNamespace, modelSnapshotNamespace)), modelSnapshotFileName); } Dependencies.OperationReporter.WriteInformation(DesignStrings.RevertingSnapshot); File.WriteAllText(modelSnapshotFile, modelSnapshotCode, Encoding.UTF8); } return(files); }
public virtual ScaffoldedMigration ScaffoldMigration( [NotNull] string migrationName, [NotNull] string rootNamespace, [CanBeNull] string subNamespace = null) { Check.NotEmpty(migrationName, nameof(migrationName)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); if (_migrationsAssembly.FindMigrationId(migrationName) != null) { throw new OperationException(DesignStrings.DuplicateMigrationName(migrationName)); } var subNamespaceDefaulted = false; if (string.IsNullOrEmpty(subNamespace)) { subNamespaceDefaulted = true; subNamespace = "Migrations"; } var lastMigration = _migrationsAssembly.Migrations.LastOrDefault(); var migrationNamespace = rootNamespace + "." + subNamespace; if (subNamespaceDefaulted) { migrationNamespace = GetNamespace(lastMigration.Value?.AsType(), migrationNamespace); } var sanitizedContextName = _contextType.Name; var genericMarkIndex = sanitizedContextName.IndexOf('`'); if (genericMarkIndex != -1) { sanitizedContextName = sanitizedContextName.Substring(0, genericMarkIndex); } if (ContainsForeignMigrations(migrationNamespace)) { if (subNamespaceDefaulted) { var builder = new StringBuilder() .Append(rootNamespace) .Append(".Migrations."); if (sanitizedContextName.EndsWith("Context", StringComparison.Ordinal)) { builder.Append(sanitizedContextName.Substring(0, sanitizedContextName.Length - 7)); } else { builder .Append(sanitizedContextName) .Append("Migrations"); } migrationNamespace = builder.ToString(); } else { _logger.LogWarning( DesignEventId.ForeignMigrations, () => DesignStrings.ForeignMigrations(migrationNamespace)); } } var modelSnapshot = _migrationsAssembly.ModelSnapshot; var lastModel = modelSnapshot?.Model; var upOperations = _modelDiffer.GetDifferences(lastModel, _model); var downOperations = upOperations.Any() ? _modelDiffer.GetDifferences(_model, lastModel) : new List <MigrationOperation>(); var migrationId = _idGenerator.GenerateId(migrationName); var modelSnapshotNamespace = GetNamespace(modelSnapshot?.GetType(), migrationNamespace); var modelSnapshotName = sanitizedContextName + "ModelSnapshot"; if (modelSnapshot != null) { var lastModelSnapshotName = modelSnapshot.GetType().Name; if (lastModelSnapshotName != modelSnapshotName) { _logger.LogDebug( DesignEventId.ReusingSnapshotName, () => DesignStrings.ReusingSnapshotName(lastModelSnapshotName)); modelSnapshotName = lastModelSnapshotName; } } if (upOperations.Any(o => o.IsDestructiveChange)) { _logger.LogWarning( DesignEventId.DestructiveOperation, () => DesignStrings.DestructiveOperation); } var migrationCode = _migrationCodeGenerator.GenerateMigration( migrationNamespace, migrationName, upOperations, downOperations); var migrationMetadataCode = _migrationCodeGenerator.GenerateMetadata( migrationNamespace, _contextType, migrationName, migrationId, _model); var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, _model); return(new ScaffoldedMigration( _migrationCodeGenerator.FileExtension, lastMigration.Key, migrationCode, migrationId, migrationMetadataCode, GetSubNamespace(rootNamespace, migrationNamespace), modelSnapshotCode, modelSnapshotName, GetSubNamespace(rootNamespace, modelSnapshotNamespace))); }
private IDictionary <Type, Func <DbContext> > FindContextTypes() { _reporter.WriteVerbose(DesignStrings.FindingContexts); var contexts = new Dictionary <Type, Func <DbContext> >(); // Look for IDesignTimeDbContextFactory implementations _reporter.WriteVerbose(DesignStrings.FindingContextFactories); var contextFactories = _startupAssembly.GetConstructibleTypes() .Where(t => typeof(IDesignTimeDbContextFactory <DbContext>).IsAssignableFrom(t)); foreach (var factory in contextFactories) { _reporter.WriteVerbose(DesignStrings.FoundContextFactory(factory.ShortDisplayName())); var manufacturedContexts = from i in factory.ImplementedInterfaces where i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDesignTimeDbContextFactory <>) select i.GenericTypeArguments[0]; foreach (var context in manufacturedContexts) { _reporter.WriteVerbose(DesignStrings.FoundDbContext(context.ShortDisplayName())); contexts.Add( context, () => CreateContextFromFactory(factory.AsType())); } } // Look for DbContext classes registered in the service provider var appServices = _appServicesFactory.Create(_args); var registeredContexts = appServices.GetServices <DbContextOptions>() .Select(o => o.ContextType); foreach (var context in registeredContexts.Where(c => !contexts.ContainsKey(c))) { _reporter.WriteVerbose(DesignStrings.FoundDbContext(context.ShortDisplayName())); contexts.Add( context, FindContextFactory(context) ?? (() => (DbContext)ActivatorUtilities.GetServiceOrCreateInstance(appServices, context))); } // Look for DbContext classes in assemblies _reporter.WriteVerbose(DesignStrings.FindingReferencedContexts); var types = _startupAssembly.GetConstructibleTypes() .Concat(_assembly.GetConstructibleTypes()) .ToList(); var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t)).Select( t => t.AsType()) .Concat( types.Where(t => typeof(Migration).IsAssignableFrom(t)) .Select(t => t.GetCustomAttribute <DbContextAttribute>()?.ContextType) .Where(t => t != null)) .Distinct(); foreach (var context in contextTypes.Where(c => !contexts.ContainsKey(c))) { _reporter.WriteVerbose(DesignStrings.FoundDbContext(context.ShortDisplayName())); contexts.Add( context, FindContextFactory(context) ?? (() => { try { return((DbContext)Activator.CreateInstance(context)); } catch (MissingMethodException ex) { throw new OperationException(DesignStrings.NoParameterlessConstructor(context.Name), ex); } })); } return(contexts); }
/// <summary> /// Scaffolds a new migration. /// </summary> /// <param name="migrationName"> The migration's name. </param> /// <param name="rootNamespace"> The project's root namespace. </param> /// <param name="subNamespace"> The migration's sub-namespace. </param> /// <param name="language"> The project's language. </param> /// <returns> The scaffolded migration. </returns> public virtual ScaffoldedMigration ScaffoldMigration( string migrationName, string rootNamespace, string subNamespace = null, string language = null) { Check.NotEmpty(migrationName, nameof(migrationName)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); if (Dependencies.MigrationsAssembly.FindMigrationId(migrationName) != null) { throw new OperationException(DesignStrings.DuplicateMigrationName(migrationName)); } var subNamespaceDefaulted = false; if (string.IsNullOrEmpty(subNamespace)) { subNamespaceDefaulted = true; subNamespace = "Migrations"; } var lastMigration = Dependencies.MigrationsAssembly.Migrations.LastOrDefault(); var migrationNamespace = rootNamespace + "." + subNamespace; if (subNamespaceDefaulted) { migrationNamespace = GetNamespace(lastMigration.Value?.AsType(), migrationNamespace); } var sanitizedContextName = _contextType.Name; var genericMarkIndex = sanitizedContextName.IndexOf('`'); if (genericMarkIndex != -1) { sanitizedContextName = sanitizedContextName.Substring(0, genericMarkIndex); } if (ContainsForeignMigrations(migrationNamespace)) { if (subNamespaceDefaulted) { var builder = new StringBuilder() .Append(rootNamespace) .Append(".Migrations."); if (sanitizedContextName.EndsWith("Context", StringComparison.Ordinal)) { builder.Append(sanitizedContextName, 0, sanitizedContextName.Length - 7); } else { builder .Append(sanitizedContextName) .Append("Migrations"); } migrationNamespace = builder.ToString(); } else { Dependencies.OperationReporter.WriteWarning(DesignStrings.ForeignMigrations(migrationNamespace)); } } var modelSnapshot = Dependencies.MigrationsAssembly.ModelSnapshot; var lastModel = Dependencies.SnapshotModelProcessor.Process(modelSnapshot?.Model); var upOperations = Dependencies.MigrationsModelDiffer.GetDifferences(lastModel, Dependencies.Model); var downOperations = upOperations.Count > 0 ? Dependencies.MigrationsModelDiffer.GetDifferences(Dependencies.Model, lastModel) : new List <MigrationOperation>(); var migrationId = Dependencies.MigrationsIdGenerator.GenerateId(migrationName); var modelSnapshotNamespace = GetNamespace(modelSnapshot?.GetType(), migrationNamespace); var modelSnapshotName = sanitizedContextName + "ModelSnapshot"; if (modelSnapshot != null) { var lastModelSnapshotName = modelSnapshot.GetType().Name; if (lastModelSnapshotName != modelSnapshotName) { Dependencies.OperationReporter.WriteVerbose(DesignStrings.ReusingSnapshotName(lastModelSnapshotName)); modelSnapshotName = lastModelSnapshotName; } } if (upOperations.Any(o => o.IsDestructiveChange)) { Dependencies.OperationReporter.WriteWarning(DesignStrings.DestructiveOperation); } var codeGenerator = Dependencies.MigrationsCodeGeneratorSelector.Select(language); var migrationCode = codeGenerator.GenerateMigration( migrationNamespace, migrationName, upOperations, downOperations); var migrationMetadataCode = codeGenerator.GenerateMetadata( migrationNamespace, _contextType, migrationName, migrationId, Dependencies.Model); var modelSnapshotCode = codeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, Dependencies.Model); return(new ScaffoldedMigration( codeGenerator.FileExtension, lastMigration.Key, migrationCode, migrationId, migrationMetadataCode, GetSubNamespace(rootNamespace, migrationNamespace), modelSnapshotCode, modelSnapshotName, GetSubNamespace(rootNamespace, modelSnapshotNamespace))); }
// TODO: DRY (file names) public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotNull] string rootNamespace, bool force) { Check.NotEmpty(projectDir, nameof(projectDir)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); var files = new MigrationFiles(); var modelSnapshot = _migrationsAssembly.ModelSnapshot; if (modelSnapshot == null) { throw new OperationException(DesignStrings.NoSnapshot); } var language = _migrationCodeGenerator.FileExtension; IModel model = null; var migrations = _migrationsAssembly.Migrations .Select(m => _migrationsAssembly.CreateMigration(m.Value, _activeProvider)) .ToList(); if (migrations.Count != 0) { var migration = migrations[migrations.Count - 1]; model = migration.TargetModel; if (!_modelDiffer.HasDifferences(model, modelSnapshot.Model)) { if (force) { _logger.LogWarning( DesignEventId.ForceRemoveMigration, () => DesignStrings.ForceRemoveMigration(migration.GetId())); } else if (_historyRepository.GetAppliedMigrations().Any( e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase))) { throw new OperationException(DesignStrings.UnapplyMigration(migration.GetId())); } var migrationFileName = migration.GetId() + language; var migrationFile = TryGetProjectFile(projectDir, migrationFileName); if (migrationFile != null) { _logger.LogInformation( DesignEventId.RemovingMigration, () => DesignStrings.RemovingMigration(migration.GetId())); File.Delete(migrationFile); files.MigrationFile = migrationFile; } else { _logger.LogWarning( DesignEventId.NoMigrationFile, () => DesignStrings.NoMigrationFile(migrationFileName, migration.GetType().ShortDisplayName())); } var migrationMetadataFileName = migration.GetId() + ".Designer" + language; var migrationMetadataFile = TryGetProjectFile(projectDir, migrationMetadataFileName); if (migrationMetadataFile != null) { File.Delete(migrationMetadataFile); files.MetadataFile = migrationMetadataFile; } else { _logger.LogDebug( DesignEventId.NoMigrationMetadataFile, () => DesignStrings.NoMigrationMetadataFile(migrationMetadataFileName)); } model = migrations.Count > 1 ? migrations[migrations.Count - 2].TargetModel : null; } else { _logger.LogDebug( DesignEventId.ManuallyDeleted, () => DesignStrings.ManuallyDeleted); } } var modelSnapshotName = modelSnapshot.GetType().Name; var modelSnapshotFileName = modelSnapshotName + language; var modelSnapshotFile = TryGetProjectFile(projectDir, modelSnapshotFileName); if (model == null) { if (modelSnapshotFile != null) { _logger.LogInformation( DesignEventId.RemovingSnapshot, () => DesignStrings.RemovingSnapshot); File.Delete(modelSnapshotFile); files.SnapshotFile = modelSnapshotFile; } else { _logger.LogWarning( DesignEventId.NoSnapshotFile, () => DesignStrings.NoSnapshotFile(modelSnapshotFileName, modelSnapshot.GetType().ShortDisplayName())); } } else { var modelSnapshotNamespace = modelSnapshot.GetType().Namespace; Debug.Assert(!string.IsNullOrEmpty(modelSnapshotNamespace)); var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, model); if (modelSnapshotFile == null) { modelSnapshotFile = Path.Combine( GetDirectory(projectDir, null, GetSubNamespace(rootNamespace, modelSnapshotNamespace)), modelSnapshotFileName); } _logger.LogInformation( DesignEventId.RevertingSnapshot, () => DesignStrings.RevertingSnapshot); File.WriteAllText(modelSnapshotFile, modelSnapshotCode, Encoding.UTF8); } return(files); }
/// <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> protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder modelBuilder, [NotNull] DatabaseForeignKey foreignKey) { Check.NotNull(modelBuilder, nameof(modelBuilder)); Check.NotNull(foreignKey, nameof(foreignKey)); if (foreignKey.PrincipalTable == null) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalTableNotFound(foreignKey.DisplayName())); return(null); } if (foreignKey.Table == null) { return(null); } var dependentEntityType = modelBuilder.Model.FindEntityType(GetEntityTypeName(foreignKey.Table)); if (dependentEntityType == null) { return(null); } var unmappedDependentColumns = foreignKey.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedDependentColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPropertyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedDependentColumns))); return(null); } var dependentProperties = foreignKey.Columns .Select(GetPropertyName) .Select(name => dependentEntityType.FindProperty(name)) .ToList() .AsReadOnly(); var principalEntityType = modelBuilder.Model.FindEntityType(GetEntityTypeName(foreignKey.PrincipalTable)); if (principalEntityType == null) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalTableScaffoldingError( foreignKey.DisplayName(), foreignKey.PrincipalTable.DisplayName())); return(null); } var unmappedPrincipalColumns = foreignKey.PrincipalColumns .Where(pc => principalEntityType.FindProperty(GetPropertyName(pc)) == null) .Select(pc => pc.Name) .ToList(); if (unmappedPrincipalColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPropertyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedPrincipalColumns))); return(null); } var principalPropertiesMap = foreignKey.PrincipalColumns .Select( fc => (property: principalEntityType.FindProperty(GetPropertyName(fc)), column: fc)).ToList(); var principalProperties = principalPropertiesMap .Select(tuple => tuple.property) .ToList(); var principalKey = principalEntityType.FindKey(principalProperties); if (principalKey == null) { var index = principalEntityType.FindIndex(principalProperties.AsReadOnly()); if (index?.IsUnique == true) { // ensure all principal properties are non-nullable even if the columns // are nullable on the database. EF's concept of a key requires this. var nullablePrincipalProperties = principalPropertiesMap.Where(tuple => tuple.property.IsNullable).ToList(); if (nullablePrincipalProperties.Count > 0) { _reporter.WriteWarning( DesignStrings.ForeignKeyPrincipalEndContainsNullableColumns( foreignKey.DisplayName(), index.Relational().Name, nullablePrincipalProperties.Select(tuple => tuple.column.DisplayName()).ToList() .Aggregate((a, b) => a + "," + b))); nullablePrincipalProperties .ToList() .ForEach(tuple => tuple.property.IsNullable = false); } principalKey = principalEntityType.AddKey(principalProperties); } else { var principalColumns = foreignKey.PrincipalColumns.Select(c => c.Name).ToList(); _reporter.WriteWarning( DesignStrings.ForeignKeyScaffoldErrorPrincipalKeyNotFound( foreignKey.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, principalColumns), principalEntityType.DisplayName())); return(null); } } var key = dependentEntityType.AddForeignKey( dependentProperties, principalKey, principalEntityType); var dependentKey = dependentEntityType.FindKey(dependentProperties); var dependentIndex = dependentEntityType.FindIndex(dependentProperties); key.IsUnique = dependentKey != null || dependentIndex?.IsUnique == true; if (!string.IsNullOrEmpty(foreignKey.Name) && foreignKey.Name != ConstraintNamer.GetDefaultName(key)) { key.Relational().ConstraintName = foreignKey.Name; } AssignOnDeleteAction(foreignKey, key); key.AddAnnotations(foreignKey.GetAnnotations()); return(key); }
public void Sequences() { using (var scratch = SqlServerTestStore.Create("SqlServerE2E")) { scratch.ExecuteNonQuery(@" CREATE SEQUENCE CountByTwo START WITH 1 INCREMENT BY 2; CREATE SEQUENCE CyclicalCountByThree START WITH 6 INCREMENT BY 3 MAXVALUE 27 MINVALUE 0 CYCLE; CREATE SEQUENCE TinyIntSequence AS tinyint START WITH 1; CREATE SEQUENCE SmallIntSequence AS smallint START WITH 1; CREATE SEQUENCE IntSequence AS int START WITH 1; CREATE SEQUENCE DecimalSequence AS decimal; CREATE SEQUENCE NumericSequence AS numeric;"); var expectedFileSet = new FileSet( new FileSystemFileService(), Path.Combine("ReverseEngineering", "Expected"), contents => contents.Replace("{{connectionString}}", scratch.ConnectionString)) { Files = new List <string> { "SequenceContext.cs" } }; var filePaths = Generator.Generate( scratch.ConnectionString, Enumerable.Empty <string>(), Enumerable.Empty <string>(), TestProjectDir + Path.DirectorySeparatorChar, outputPath: null, // not used for this test rootNamespace: TestNamespace, contextName: "SequenceContext", useDataAnnotations: false, overwriteFiles: false, useDatabaseNames: false); var actualFileSet = new FileSet(InMemoryFiles, Path.GetFullPath(TestProjectDir)) { Files = new[] { filePaths.ContextFile }.Concat(filePaths.EntityTypeFiles).Select(Path.GetFileName).ToList() }; Assert.Contains("warn: " + DesignStrings.BadSequenceType("DecimalSequence", "decimal"), _reporter.Messages); Assert.Contains("warn: " + DesignStrings.BadSequenceType("NumericSequence", "numeric"), _reporter.Messages); Assert.Equal(2, _reporter.Messages.Count(m => m.StartsWith("warn: "))); AssertEqualFileContents(expectedFileSet, actualFileSet); AssertCompile(actualFileSet); } }
/// <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> protected virtual PropertyBuilder VisitColumn([NotNull] EntityTypeBuilder builder, [NotNull] DatabaseColumn column) { Check.NotNull(builder, nameof(builder)); Check.NotNull(column, nameof(column)); var typeScaffoldingInfo = GetTypeScaffoldingInfo(column); if (typeScaffoldingInfo == null) { _unmappedColumns.Add(column); _reporter.WriteWarning( DesignStrings.CannotFindTypeMappingForColumn(column.DisplayName(), column.StoreType)); return(null); } var clrType = typeScaffoldingInfo.ClrType; if (column.IsNullable) { clrType = clrType.MakeNullable(); } if (clrType == typeof(bool) && column.DefaultValueSql != null) { _reporter.WriteWarning( DesignStrings.NonNullableBoooleanColumnHasDefaultConstraint(column.DisplayName())); clrType = clrType.MakeNullable(); } var property = builder.Property(clrType, GetPropertyName(column)); property.HasColumnName(column.Name); if (!typeScaffoldingInfo.IsInferred && !string.IsNullOrWhiteSpace(column.StoreType)) { property.HasColumnType(column.StoreType); } if (typeScaffoldingInfo.ScaffoldUnicode.HasValue) { property.IsUnicode(typeScaffoldingInfo.ScaffoldUnicode.Value); } if (typeScaffoldingInfo.ScaffoldFixedLength == true) { property.IsFixedLength(); } if (typeScaffoldingInfo.ScaffoldMaxLength.HasValue) { property.HasMaxLength(typeScaffoldingInfo.ScaffoldMaxLength.Value); } if (column.ValueGenerated == ValueGenerated.OnAdd) { property.ValueGeneratedOnAdd(); } if (column.ValueGenerated == ValueGenerated.OnUpdate) { property.ValueGeneratedOnUpdate(); } if (column.ValueGenerated == ValueGenerated.OnAddOrUpdate) { property.ValueGeneratedOnAddOrUpdate(); } if (column.DefaultValueSql != null) { property.HasDefaultValueSql(column.DefaultValueSql); } if (column.ComputedColumnSql != null) { property.HasComputedColumnSql(column.ComputedColumnSql); } if (!(column.Table.PrimaryKey?.Columns.Contains(column) ?? false)) { property.IsRequired(!column.IsNullable); } if ((bool?)column[ScaffoldingAnnotationNames.ConcurrencyToken] == true) { property.IsConcurrencyToken(); } property.Metadata.Scaffolding().ColumnOrdinal = column.Table.Columns.IndexOf(column); property.Metadata.AddAnnotations( column.GetAnnotations().Where( a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken)); return(property); }
/// <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> protected virtual KeyBuilder VisitPrimaryKey([NotNull] EntityTypeBuilder builder, [NotNull] DatabaseTable table) { Check.NotNull(builder, nameof(builder)); Check.NotNull(table, nameof(table)); var primaryKey = table.PrimaryKey; if (primaryKey == null) { _reporter.WriteWarning(DesignStrings.MissingPrimaryKey(table.DisplayName())); return(null); } var unmappedColumns = primaryKey.Columns .Where(c => _unmappedColumns.Contains(c)) .Select(c => c.Name) .ToList(); if (unmappedColumns.Count > 0) { _reporter.WriteWarning( DesignStrings.PrimaryKeyErrorPropertyNotFound( table.DisplayName(), string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, unmappedColumns))); return(null); } var keyBuilder = builder.HasKey(primaryKey.Columns.Select(GetPropertyName).ToArray()); if (primaryKey.Columns.Count == 1 && primaryKey.Columns[0].ValueGenerated == null && primaryKey.Columns[0].DefaultValueSql == null) { var property = builder.Metadata.FindProperty(GetPropertyName(primaryKey.Columns[0]))?.AsProperty(); if (property != null) { var dummyLogger = new DiagnosticsLogger <DbLoggerCategory.Model>( new ScopedLoggerFactory(new LoggerFactory(), dispose: true), new LoggingOptions(), new DiagnosticListener(""), new LoggingDefinitions()); var conventionalValueGenerated = new RelationalValueGeneratorConvention(dummyLogger).GetValueGenerated(property); if (conventionalValueGenerated == ValueGenerated.OnAdd) { property.ValueGenerated = ValueGenerated.Never; } } } if (!string.IsNullOrEmpty(primaryKey.Name) && primaryKey.Name != ConstraintNamer.GetDefaultName(keyBuilder.Metadata)) { keyBuilder.HasName(primaryKey.Name); } keyBuilder.Metadata.AddAnnotations(primaryKey.GetAnnotations()); return(keyBuilder); }
public void GetMigrations_throws_when_target_and_migrations_assemblies_mismatch() { using (var directory = new TempDirectory()) { var targetDir = directory.Path; var source = new BuildSource { TargetDir = targetDir, References = { BuildReference.ByName("System.Diagnostics.DiagnosticSource", true), BuildReference.ByName("System.Interactive.Async", true), BuildReference.ByName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), BuildReference.ByName("Microsoft.AspNetCore.Hosting.Abstractions", true), BuildReference.ByName("Microsoft.EntityFrameworkCore", true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Design", true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational", true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational.Design", true), BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer", true), BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions", true), BuildReference.ByName("Microsoft.Extensions.Caching.Memory", true), BuildReference.ByName("Microsoft.Extensions.Configuration.Abstractions", true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection", true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions", true), BuildReference.ByName("Microsoft.Extensions.FileProviders.Abstractions", true), BuildReference.ByName("Microsoft.Extensions.Logging", true), BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions", true), BuildReference.ByName("Microsoft.Extensions.Options", true), BuildReference.ByName("Remotion.Linq", true) }, Sources = { @" using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; namespace MyProject { internal class MyContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( ""Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MyProject.MyContext;Integrated Security=True"", b => b.MigrationsAssembly(""UnknownAssembly"")); } } namespace Migrations { [DbContext(typeof(MyContext))] [Migration(""20151215152142_MyMigration"")] public class MyMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { } } } }" } }; var build = source.Build(); using (var executor = CreateExecutorFromBuildResult(build, "MyProject")) { var ex = Assert.Throws <WrappedException>( () => executor.GetMigrations("MyContext")); Assert.Equal( DesignStrings.MigrationsAssemblyMismatch(build.TargetName, "UnknownAssembly"), ex.Message); } } }
private void GenerateProperty(IProperty property, bool useDataAnnotations) { var lines = new List <string> { $".{nameof(EntityTypeBuilder.Property)}(e => e.{property.Name})" }; var annotations = property.GetAnnotations().ToList(); RemoveAnnotation(ref annotations, CoreAnnotationNames.MaxLength); RemoveAnnotation(ref annotations, CoreAnnotationNames.Precision); RemoveAnnotation(ref annotations, CoreAnnotationNames.Scale); RemoveAnnotation(ref annotations, CoreAnnotationNames.TypeMapping); RemoveAnnotation(ref annotations, CoreAnnotationNames.Unicode); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ColumnName); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ViewColumnName); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ColumnType); RemoveAnnotation(ref annotations, RelationalAnnotationNames.DefaultValue); RemoveAnnotation(ref annotations, RelationalAnnotationNames.DefaultValueSql); RemoveAnnotation(ref annotations, RelationalAnnotationNames.Comment); RemoveAnnotation(ref annotations, RelationalAnnotationNames.Collation); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ComputedColumnSql); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ComputedColumnIsStored); RemoveAnnotation(ref annotations, RelationalAnnotationNames.IsFixedLength); RemoveAnnotation(ref annotations, RelationalAnnotationNames.TableColumnMappings); RemoveAnnotation(ref annotations, RelationalAnnotationNames.ViewColumnMappings); RemoveAnnotation(ref annotations, RelationalAnnotationNames.RelationalOverrides); RemoveAnnotation(ref annotations, ScaffoldingAnnotationNames.ColumnOrdinal); if (!useDataAnnotations) { if (!property.IsNullable && property.ClrType.IsNullableType() && !property.IsPrimaryKey()) { lines.Add($".{nameof(PropertyBuilder.IsRequired)}()"); } var columnName = property.GetColumnName(); if (columnName != null && columnName != property.Name) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasColumnName)}" + $"({_code.Literal(columnName)})"); } var viewColumnName = property.GetViewColumnName(); if (viewColumnName != null && viewColumnName != columnName) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasViewColumnName)}" + $"({_code.Literal(columnName)})"); } var columnType = property.GetConfiguredColumnType(); if (columnType != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasColumnType)}" + $"({_code.Literal(columnType)})"); } var maxLength = property.GetMaxLength(); if (maxLength.HasValue) { lines.Add( $".{nameof(PropertyBuilder.HasMaxLength)}" + $"({_code.Literal(maxLength.Value)})"); } } var precision = property.GetPrecision(); var scale = property.GetScale(); if (precision != null && scale != null && scale != 0) { lines.Add( $".{nameof(PropertyBuilder.HasPrecision)}" + $"({_code.Literal(precision.Value)}, {_code.Literal(scale.Value)})"); } else if (precision != null) { lines.Add( $".{nameof(PropertyBuilder.HasPrecision)}" + $"({_code.Literal(precision.Value)})"); } if (property.IsUnicode() != null) { lines.Add( $".{nameof(PropertyBuilder.IsUnicode)}" + $"({(property.IsUnicode() == false ? "false" : "")})"); } if (property.IsFixedLength() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.IsFixedLength)}()"); } if (property.GetDefaultValue() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}" + $"({_code.UnknownLiteral(property.GetDefaultValue())})"); } if (property.GetDefaultValueSql() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValueSql)}" + $"({_code.Literal(property.GetDefaultValueSql())})"); } if (property.GetComputedColumnSql() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasComputedColumnSql)}" + $"({_code.Literal(property.GetComputedColumnSql())}" + (property.GetComputedColumnIsStored() is bool computedColumnIsStored ? $", stored: {_code.Literal(computedColumnIsStored)})" : ")")); } if (property.GetComment() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasComment)}" + $"({_code.Literal(property.GetComment())})"); } if (property.GetCollation() != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.UseCollation)}" + $"({_code.Literal(property.GetCollation())})"); } var valueGenerated = property.ValueGenerated; var isRowVersion = false; if (((IConventionProperty)property).GetValueGeneratedConfigurationSource().HasValue && RelationalValueGenerationConvention.GetValueGenerated(property) != valueGenerated) { var methodName = valueGenerated switch { ValueGenerated.OnAdd => nameof(PropertyBuilder.ValueGeneratedOnAdd), ValueGenerated.OnAddOrUpdate => property.IsConcurrencyToken ? nameof(PropertyBuilder.IsRowVersion) : nameof(PropertyBuilder.ValueGeneratedOnAddOrUpdate), ValueGenerated.OnUpdate => nameof(PropertyBuilder.ValueGeneratedOnUpdate), ValueGenerated.Never => nameof(PropertyBuilder.ValueGeneratedNever), _ => throw new InvalidOperationException(DesignStrings.UnhandledEnumValue($"{nameof(ValueGenerated)}.{valueGenerated}")) }; lines.Add($".{methodName}()"); } if (property.IsConcurrencyToken && !isRowVersion) { lines.Add($".{nameof(PropertyBuilder.IsConcurrencyToken)}()"); } var annotationsToRemove = new List <IAnnotation>(); foreach (var annotation in annotations) { if (annotation.Value == null || _annotationCodeGenerator.IsHandledByConvention(property, annotation)) { annotationsToRemove.Add(annotation); } else { var methodCall = _annotationCodeGenerator.GenerateFluentApi(property, annotation); if (methodCall != null) { lines.Add(_code.Fragment(methodCall)); annotationsToRemove.Add(annotation); } } } lines.AddRange(GenerateAnnotations(annotations.Except(annotationsToRemove))); switch (lines.Count) { case 1: return; case 2: lines = new List <string> { lines[0] + lines[1] }; break; } AppendMultiLineFluentApi(property.DeclaringEntityType, lines); }
private void GenerateProperty(IProperty property) { var lines = new List <string> { $".{nameof(EntityTypeBuilder.Property)}({_code.Lambda(new[] { property.Name }, " e ")})" }; var annotations = _annotationCodeGenerator .FilterIgnoredAnnotations(property.GetAnnotations()) .ToDictionary(a => a.Name, a => a); _annotationCodeGenerator.RemoveAnnotationsHandledByConventions(property, annotations); annotations.Remove(ScaffoldingAnnotationNames.ColumnOrdinal); if (_useDataAnnotations) { // Strip out any annotations handled as attributes - these are already handled when generating // the entity's properties // Only relational ones need to be removed here. Core ones are already removed by FilterIgnoredAnnotations annotations.Remove(RelationalAnnotationNames.ColumnName); annotations.Remove(RelationalAnnotationNames.ColumnType); _ = _annotationCodeGenerator.GenerateDataAnnotationAttributes(property, annotations); } else { if ((!_useNullableReferenceTypes || property.ClrType.IsValueType) && !property.IsNullable && property.ClrType.IsNullableType() && !property.IsPrimaryKey()) { lines.Add($".{nameof(PropertyBuilder.IsRequired)}()"); } var columnType = property.GetConfiguredColumnType(); if (columnType != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasColumnType)}({_code.Literal(columnType)})"); annotations.Remove(RelationalAnnotationNames.ColumnType); } var maxLength = property.GetMaxLength(); if (maxLength.HasValue) { lines.Add( $".{nameof(PropertyBuilder.HasMaxLength)}({_code.Literal(maxLength.Value)})"); } var precision = property.GetPrecision(); var scale = property.GetScale(); if (precision != null && scale != null && scale != 0) { lines.Add( $".{nameof(PropertyBuilder.HasPrecision)}({_code.Literal(precision.Value)}, {_code.Literal(scale.Value)})"); } else if (precision != null) { lines.Add( $".{nameof(PropertyBuilder.HasPrecision)}({_code.Literal(precision.Value)})"); } if (property.IsUnicode() != null) { lines.Add( $".{nameof(PropertyBuilder.IsUnicode)}({(property.IsUnicode() == false ? "false" : "")})"); } } if (property.TryGetDefaultValue(out var defaultValue)) { if (defaultValue == DBNull.Value) { lines.Add($".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}()"); annotations.Remove(RelationalAnnotationNames.DefaultValue); } else if (defaultValue != null) { lines.Add( $".{nameof(RelationalPropertyBuilderExtensions.HasDefaultValue)}({_code.UnknownLiteral(defaultValue)})"); annotations.Remove(RelationalAnnotationNames.DefaultValue); } } var valueGenerated = property.ValueGenerated; var isRowVersion = false; if (((IConventionProperty)property).GetValueGeneratedConfigurationSource() is ConfigurationSource valueGeneratedConfigurationSource && valueGeneratedConfigurationSource != ConfigurationSource.Convention && ValueGenerationConvention.GetValueGenerated(property) != valueGenerated) { var methodName = valueGenerated switch { ValueGenerated.OnAdd => nameof(PropertyBuilder.ValueGeneratedOnAdd), ValueGenerated.OnAddOrUpdate => property.IsConcurrencyToken ? nameof(PropertyBuilder.IsRowVersion) : nameof(PropertyBuilder.ValueGeneratedOnAddOrUpdate), ValueGenerated.OnUpdate => nameof(PropertyBuilder.ValueGeneratedOnUpdate), ValueGenerated.Never => nameof(PropertyBuilder.ValueGeneratedNever), _ => throw new InvalidOperationException(DesignStrings.UnhandledEnumValue($"{nameof(ValueGenerated)}.{valueGenerated}")) }; lines.Add($".{methodName}()"); } if (property.IsConcurrencyToken && !isRowVersion) { lines.Add($".{nameof(PropertyBuilder.IsConcurrencyToken)}()"); } lines.AddRange( _annotationCodeGenerator.GenerateFluentApiCalls(property, annotations).Select(m => _code.Fragment(m)) .Concat(GenerateAnnotations(annotations.Values))); switch (lines.Count) { case 1: return; case 2: lines = new List <string> { lines[0] + lines[1] }; break; } AppendMultiLineFluentApi(property.DeclaringEntityType, lines); }
/// <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 virtual ReverseEngineerFiles Generate( string connectionString, IEnumerable <string> tables, IEnumerable <string> schemas, string projectPath, string outputPath, string rootNamespace, string contextName, bool useDataAnnotations, bool overwriteFiles, bool useDatabaseNames) { Check.NotEmpty(connectionString, nameof(connectionString)); Check.NotNull(tables, nameof(tables)); Check.NotNull(schemas, nameof(schemas)); Check.NotEmpty(projectPath, nameof(projectPath)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); if (!string.IsNullOrWhiteSpace(contextName) && (!_cSharpUtilities.IsValidIdentifier(contextName) || _cSharpUtilities.IsCSharpKeyword(contextName))) { throw new ArgumentException( DesignStrings.ContextClassNotValidCSharpIdentifier(contextName)); } var databaseModel = _databaseModelFactory.Create(connectionString, tables, schemas); var model = _factory.Create(databaseModel, useDatabaseNames); if (model == null) { throw new InvalidOperationException( DesignStrings.ProviderReturnedNullModel( _factory.GetType().ShortDisplayName())); } outputPath = string.IsNullOrWhiteSpace(outputPath) ? null : outputPath; var subNamespace = SubnamespaceFromOutputPath(projectPath, outputPath); var @namespace = rootNamespace; if (!string.IsNullOrEmpty(subNamespace)) { @namespace += "." + subNamespace; } if (string.IsNullOrEmpty(contextName)) { contextName = DefaultDbContextName; var annotatedName = model.Scaffolding().DatabaseName; if (!string.IsNullOrEmpty(annotatedName)) { contextName = _cSharpUtilities.GenerateCSharpIdentifier( annotatedName + DbContextSuffix, existingIdentifiers: null, singularizePluralizer: null); } } CheckOutputFiles(outputPath ?? projectPath, contextName, model, overwriteFiles); return(ScaffoldingCodeGenerator.WriteCode(model, outputPath ?? projectPath, @namespace, contextName, connectionString, useDataAnnotations)); }
/// <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(toolsVersion, 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, startupAssembly.Value, _projectDir, rootNamespace, language, designArgs)); _migrationsOperations = new LazyRef <MigrationsOperations>( () => new MigrationsOperations( reporter, assembly.Value, startupAssembly.Value, _projectDir, rootNamespace, language, designArgs)); }
/// <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 virtual ScaffoldedModel ScaffoldModel( string connectionString, IEnumerable <string> tables, IEnumerable <string> schemas, string @namespace, string language, string contextDir, string contextName, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions) { Check.NotEmpty(connectionString, nameof(connectionString)); Check.NotNull(tables, nameof(tables)); Check.NotNull(schemas, nameof(schemas)); Check.NotEmpty(@namespace, nameof(@namespace)); Check.NotNull(language, nameof(language)); 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, tables, schemas); 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.Scaffolding().DatabaseName; if (!string.IsNullOrEmpty(annotatedName)) { contextName = _cSharpUtilities.GenerateCSharpIdentifier( annotatedName + DbContextSuffix, existingIdentifiers: null, singularizePluralizer: null); } } var codeGenerator = ModelCodeGeneratorSelector.Select(language); return(codeGenerator.GenerateModel(model, @namespace, contextDir ?? string.Empty, contextName, connectionString, codeOptions)); }
public virtual ScaffoldedModel ScaffoldModel( string connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions) { Check.NotEmpty(connectionString, nameof(connectionString)); Check.NotNull(databaseOptions, nameof(databaseOptions)); Check.NotNull(modelOptions, nameof(modelOptions)); Check.NotNull(codeOptions, nameof(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)); }