Skip to content

Commit

Permalink
RevEng: Add DatabaseModelFactoryOptions
Browse files Browse the repository at this point in the history
Also adds an abstract base class for IDatabaseModelFactory

Resolves #14602
  • Loading branch information
bricelam committed Mar 21, 2019
1 parent dc55d3a commit 4958d11
Show file tree
Hide file tree
Showing 13 changed files with 110 additions and 47 deletions.
3 changes: 1 addition & 2 deletions src/EFCore.Design/Design/Internal/DatabaseOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ public class DatabaseOperations

var scaffoldedModel = scaffolder.ScaffoldModel(
connectionString,
tables,
schemas,
new DatabaseModelFactoryOptions(tables, schemas),
_rootNamespace,
modelNamespace,
contextNamespace,
Expand Down
7 changes: 2 additions & 5 deletions src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using JetBrains.Annotations;

namespace Microsoft.EntityFrameworkCore.Scaffolding
Expand All @@ -15,8 +14,7 @@ public interface IReverseEngineerScaffolder
/// Scaffolds a model from a database schema.
/// </summary>
/// <param name="connectionString"> A connection string to the database. </param>
/// <param name="tables"> A list of tables to include. Empty to include all tables. </param>
/// <param name="schemas"> A list of schemas to include. Empty to include all schemas. </param>
/// <param name="options"> The options specifying which metadata to read from the database. </param>
/// <param name="rootNamespace"> The namespace of the project. </param>
/// <param name="modelNamespace"> The namespace for model classes. </param>
/// <param name="contextNamespace"> The namespace for context class. </param>
Expand All @@ -28,8 +26,7 @@ public interface IReverseEngineerScaffolder
/// <returns> The scaffolded model. </returns>
ScaffoldedModel ScaffoldModel(
[NotNull] string connectionString,
[NotNull] IEnumerable<string> tables,
[NotNull] IEnumerable<string> schemas,
[NotNull] DatabaseModelFactoryOptions options,
[NotNull] string rootNamespace,
[NotNull] string modelNamespace,
[NotNull] string contextNamespace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ public class ReverseEngineerScaffolder : IReverseEngineerScaffolder
/// </summary>
public virtual ScaffoldedModel ScaffoldModel(
string connectionString,
IEnumerable<string> tables,
IEnumerable<string> schemas,
DatabaseModelFactoryOptions options,
string rootNamespace,
string modelNamespace,
string contextNamespace,
Expand All @@ -80,8 +79,7 @@ public class ReverseEngineerScaffolder : IReverseEngineerScaffolder
ModelCodeGenerationOptions codeOptions)
{
Check.NotEmpty(connectionString, nameof(connectionString));
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));
Check.NotNull(options, nameof(options));
Check.NotEmpty(modelNamespace, nameof(modelNamespace));
Check.NotEmpty(contextNamespace, nameof(contextNamespace));
Check.NotNull(modelOptions, nameof(modelOptions));
Expand All @@ -101,7 +99,7 @@ public class ReverseEngineerScaffolder : IReverseEngineerScaffolder
codeOptions.SuppressConnectionStringWarning = true;
}

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

if (model == null)
Expand Down
32 changes: 32 additions & 0 deletions src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Data.Common;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;

namespace Microsoft.EntityFrameworkCore.Scaffolding
{
/// <summary>
/// Base class used by database providers to reverse engineer a database into a <see cref="DatabaseModel" />.
/// </summary>
public abstract class DatabaseModelFactory : IDatabaseModelFactory
{
/// <summary>
/// Connects to the database using the given connection string and creates a <see cref="DatabaseModel" />
/// for the database.
/// </summary>
/// <param name="connectionString"> The connection string for the database to reverse engineer. </param>
/// <param name="options"> The options specifying which metadata to read. </param>
/// <returns> The database model. </returns>
public abstract DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options);

/// <summary>
/// Connects to the database using the given connection and creates a <see cref="DatabaseModel" />
/// for the database.
/// </summary>
/// <param name="connection"> The connection to the database to reverse engineer. </param>
/// <param name="options"> The options specifying which metadata to read. </param>
/// <returns> The database model. </returns>
public abstract DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options);
}
}
39 changes: 39 additions & 0 deletions src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Scaffolding
{
/// <summary>
/// Specifies which metadata to read from the database.
/// </summary>
public class DatabaseModelFactoryOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="DatabaseModelFactoryOptions" /> class.
/// </summary>
/// <param name="tables"> A list of tables to include. Empty to include all tables. </param>
/// <param name="schemas"> A list of schemas to include. Empty to include all schemas. </param>
public DatabaseModelFactoryOptions([NotNull] IEnumerable<string> tables, [NotNull] IEnumerable<string> schemas)
{
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));

Tables = tables;
Schemas = schemas;
}

/// <summary>
/// Gets the list of tables to include. If empty, include all tables.
/// </summary>
public virtual IEnumerable<string> Tables { get; }

/// <summary>
/// Gets the list of schemas to include. If empty, include all schemas.
/// </summary>
public virtual IEnumerable<string> Schemas { get; }
}
}
11 changes: 4 additions & 7 deletions src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Data.Common;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
Expand All @@ -19,19 +18,17 @@ public interface IDatabaseModelFactory
/// for the database.
/// </summary>
/// <param name="connectionString"> The connection string for the database to reverse engineer. </param>
/// <param name="tables"> The tables to include in the model, or an empty enumerable to include all. </param>
/// <param name="schemas"> The schema to include in the model, or an empty enumerable to include all. </param>
/// <param name="options"> The options specifying which metadata to read. </param>
/// <returns> The database model. </returns>
DatabaseModel Create([NotNull] string connectionString, [NotNull] IEnumerable<string> tables, [NotNull] IEnumerable<string> schemas);
DatabaseModel Create([NotNull] string connectionString, [NotNull] DatabaseModelFactoryOptions options);

/// <summary>
/// Connects to the database using the given connection and creates a <see cref="DatabaseModel" />
/// for the database.
/// </summary>
/// <param name="connection"> The connection to the database to reverse engineer. </param>
/// <param name="tables"> The tables to include in the model, or an empty enumerable to include all. </param>
/// <param name="schemas"> The schema to include in the model, or an empty enumerable to include all. </param>
/// <param name="options"> The options specifying which metadata to read. </param>
/// <returns> The database model. </returns>
DatabaseModel Create([NotNull] DbConnection connection, [NotNull] IEnumerable<string> tables, [NotNull] IEnumerable<string> schemas);
DatabaseModel Create([NotNull] DbConnection connection, [NotNull] DatabaseModelFactoryOptions options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal
/// 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 class SqlServerDatabaseModelFactory : IDatabaseModelFactory
public class SqlServerDatabaseModelFactory : DatabaseModelFactory
{
private readonly IDiagnosticsLogger<DbLoggerCategory.Scaffolding> _logger;

Expand Down Expand Up @@ -87,27 +87,25 @@ public SqlServerDatabaseModelFactory([NotNull] IDiagnosticsLogger<DbLoggerCatego
/// 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 DatabaseModel Create(string connectionString, IEnumerable<string> tables, IEnumerable<string> schemas)
public override DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options)
{
Check.NotEmpty(connectionString, nameof(connectionString));
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));
Check.NotNull(options, nameof(options));

using (var connection = new SqlConnection(connectionString))
{
return Create(connection, tables, schemas);
return Create(connection, options);
}
}

/// <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 DatabaseModel Create(DbConnection connection, IEnumerable<string> tables, IEnumerable<string> schemas)
public override DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options)
{
Check.NotNull(connection, nameof(connection));
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));
Check.NotNull(options, nameof(options));

var databaseModel = new DatabaseModel();

Expand All @@ -124,9 +122,9 @@ public virtual DatabaseModel Create(DbConnection connection, IEnumerable<string>

var typeAliases = GetTypeAliases(connection);

var schemaList = schemas.ToList();
var schemaList = options.Schemas.ToList();
var schemaFilter = GenerateSchemaFilter(schemaList);
var tableList = tables.ToList();
var tableList = options.Tables.ToList();
var tableFilter = GenerateTableFilter(tableList.Select(Parse).ToList(), schemaFilter);

if (Version.TryParse(connection.ServerVersion, out var serverVersion)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Scaffolding.Internal
/// 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 class SqliteDatabaseModelFactory : IDatabaseModelFactory
public class SqliteDatabaseModelFactory : DatabaseModelFactory
{
private readonly IDiagnosticsLogger<DbLoggerCategory.Scaffolding> _logger;
private readonly IRelationalTypeMappingSource _typeMappingSource;
Expand All @@ -50,29 +50,27 @@ public class SqliteDatabaseModelFactory : IDatabaseModelFactory
/// 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 DatabaseModel Create(string connectionString, IEnumerable<string> tables, IEnumerable<string> schemas)
public override DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options)
{
Check.NotNull(connectionString, nameof(connectionString));
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));
Check.NotNull(options, nameof(options));

using (var connection = new SqliteConnection(connectionString))
{
return Create(connection, tables, schemas);
return Create(connection, options);
}
}

/// <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 DatabaseModel Create(DbConnection connection, IEnumerable<string> tables, IEnumerable<string> schemas)
public override DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options)
{
Check.NotNull(connection, nameof(connection));
Check.NotNull(tables, nameof(tables));
Check.NotNull(schemas, nameof(schemas));
Check.NotNull(options, nameof(options));

if (schemas.Any())
if (options.Schemas.Any())
{
_logger.SchemasNotSupportedWarning();
}
Expand All @@ -91,7 +89,7 @@ public virtual DatabaseModel Create(DbConnection connection, IEnumerable<string>
{
databaseModel.DatabaseName = GetDatabaseName(connection);

foreach (var table in GetTables(connection, tables))
foreach (var table in GetTables(connection, options.Tables))
{
table.Database = databaseModel;
databaseModel.Tables.Add(table);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ private void ValidateContextNameInReverseEngineerGenerator(string contextName)
Assert.Throws<ArgumentException>(
() => reverseEngineer.ScaffoldModel(
"connectionstring",
/* tables: */ Enumerable.Empty<string>(),
/* schemas: */ Enumerable.Empty<string>(),
new DatabaseModelFactoryOptions(
/* tables: */ Enumerable.Empty<string>(),
/* schemas: */ Enumerable.Empty<string>()),
"FakeNamespace",
"FakeNamespace",
"FakeNamespace",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public virtual void Clean(DatabaseFacade facade)
{
var databaseModelFactory = CreateDatabaseModelFactory(loggerFactory);
var databaseModel = databaseModelFactory.Create(
connection.DbConnection, Enumerable.Empty<string>(), Enumerable.Empty<string>());
connection.DbConnection,
new DatabaseModelFactoryOptions(Enumerable.Empty<string>(), Enumerable.Empty<string>()));

var operations = new List<MigrationOperation>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Data.Common;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
Expand All @@ -11,10 +10,10 @@ namespace Microsoft.EntityFrameworkCore.TestUtilities
{
public class FakeDatabaseModelFactory : IDatabaseModelFactory
{
public virtual DatabaseModel Create(string connectionString, IEnumerable<string> tables, IEnumerable<string> schemas)
public virtual DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options)
=> throw new NotImplementedException();

public virtual DatabaseModel Create(DbConnection connectio, IEnumerable<string> tables, IEnumerable<string> schemas)
public virtual DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options)
=> throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,9 @@ public void Skip_reflexive_foreign_key()
new DiagnosticListener("Fake"),
new SqlServerLoggingDefinitions()));

var databaseModel = databaseModelFactory.Create(Fixture.TestStore.ConnectionString, tables, schemas);
var databaseModel = databaseModelFactory.Create(
Fixture.TestStore.ConnectionString,
new DatabaseModelFactoryOptions(tables, schemas));
Assert.NotNull(databaseModel);
asserter(databaseModel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ public SqliteDatabaseModelFactoryTest(SqliteDatabaseModelFixture fixture)
.BuildServiceProvider()
.GetRequiredService<IDatabaseModelFactory>();

var databaseModel = databaseModelFactory.Create(Fixture.TestStore.ConnectionString, tables, schemas);
var databaseModel = databaseModelFactory.Create(
Fixture.TestStore.ConnectionString,
new DatabaseModelFactoryOptions(tables, schemas));
Assert.NotNull(databaseModel);
asserter(databaseModel);
}
Expand Down

0 comments on commit 4958d11

Please sign in to comment.