Skip to content

Commit

Permalink
Partial fix for 8332. Update the ef side to pass in the arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
lajones committed Mar 19, 2020
1 parent 20481dd commit f7216b3
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 46 deletions.
6 changes: 4 additions & 2 deletions src/EFCore.Design/Design/DbContextActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@ public static class DbContextActivator
/// <param name="contextType"> The <see cref="DbContext" /> type to instantiate. </param>
/// <param name="startupAssembly"> The application's startup assembly. </param>
/// <param name="reportHandler"> The design-time report handler. </param>
/// <param name="arguments"> Arguments passed to the <see cref="DbContext" /> constructor. </param>
/// <returns> The newly created object. </returns>
public static DbContext CreateInstance(
[NotNull] Type contextType,
[CanBeNull] Assembly startupAssembly = null,
[CanBeNull] IOperationReportHandler reportHandler = null)
[CanBeNull] IOperationReportHandler reportHandler = null,
[CanBeNull] string[] arguments = null)
{
Check.NotNull(contextType, nameof(contextType));

return new DbContextOperations(
new OperationReporter(reportHandler),
contextType.Assembly,
startupAssembly ?? contextType.Assembly,
args: Array.Empty<string>()) // TODO: Issue #8332
args: arguments ?? Array.Empty<string>())
.CreateContext(contextType.FullName);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public virtual IServiceProvider Create([NotNull] string[] args)
_reporter.WriteVerbose(DesignStrings.FindingServiceProvider);

return CreateFromHosting(args)
?? CreateEmptyServiceProvider();
?? CreateArgsServiceProvider(args);
}

private IServiceProvider CreateFromHosting(string[] args)
Expand Down Expand Up @@ -97,11 +97,13 @@ private IServiceProvider CreateFromHosting(string[] args)
}
}

private IServiceProvider CreateEmptyServiceProvider()
private IServiceProvider CreateArgsServiceProvider(string[] args)
{
_reporter.WriteVerbose(DesignStrings.NoServiceProvider);

return new ServiceCollection().BuildServiceProvider();
return new ServiceCollection()
.AddScoped(typeof(string[]), sp => args)
.BuildServiceProvider();
}
}
}
6 changes: 3 additions & 3 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class OperationExecutor : MarshalByRefObject
/// <para><c>startupTargetName</c>--The assembly name of the startup project.</para>
/// <para><c>projectDir</c>--The target project's root directory.</para>
/// <para><c>rootNamespace</c>--The target project's root namespace.</para>
/// <para><c>language</c>--The programming language to be used to generate classes.</para>
/// <para><c>appArgs</c>--Extra arguments passed into the operation.</para>
/// </summary>
/// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
/// <param name="args"> The executor arguments. </param>
Expand All @@ -61,9 +63,7 @@ public OperationExecutor([NotNull] IOperationReportHandler reportHandler, [NotNu
_projectDir = (string)args["projectDir"];
_rootNamespace = (string)args["rootNamespace"];
_language = (string)args["language"];

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

var toolsVersion = (string)args["toolsVersion"];
var runtimeVersion = ProductInfo.GetVersion();
Expand Down
4 changes: 4 additions & 0 deletions src/ef/Commands/CommandBase.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
// 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 Microsoft.DotNet.Cli.CommandLine;
using Microsoft.EntityFrameworkCore.Tools.Properties;

namespace Microsoft.EntityFrameworkCore.Tools.Commands
{
internal abstract class CommandBase
{
protected string[] RemainingArguments { get; private set; }

public virtual void Configure(CommandLineApplication command)
{
var verbose = command.Option("-v|--verbose", Resources.VerboseDescription);
var noColor = command.Option("--no-color", Resources.NoColorDescription);
var prefixOutput = command.Option("--prefix-output", Resources.PrefixDescription);

command.HandleResponseFiles = true;
RemainingArguments = command.RemainingArguments.ToArray();

command.OnExecute(
() =>
Expand Down
4 changes: 2 additions & 2 deletions src/ef/Commands/DatabaseDropCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protected override int Execute()

void LogDropCommand(Func<object, object, string> resource)
{
var result = executor.GetContextInfo(Context.Value());
var result = executor.GetContextInfo(Context.Value(), RemainingArguments);
var databaseName = result["DatabaseName"] as string;
var dataSource = result["DataSource"] as string;
Reporter.WriteInformation(resource(databaseName, dataSource));
Expand All @@ -38,7 +38,7 @@ void LogDropCommand(Func<object, object, string> resource)
}
}

executor.DropDatabase(Context.Value());
executor.DropDatabase(Context.Value(), RemainingArguments);

return base.Execute();
}
Expand Down
2 changes: 1 addition & 1 deletion src/ef/Commands/DatabaseUpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal partial class DatabaseUpdateCommand
{
protected override int Execute()
{
CreateExecutor().UpdateDatabase(_migration.Value, _connection.Value(), Context.Value());
CreateExecutor().UpdateDatabase(_migration.Value, _connection.Value(), Context.Value(), RemainingArguments);

return base.Execute();
}
Expand Down
2 changes: 1 addition & 1 deletion src/ef/Commands/DbContextInfoCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal partial class DbContextInfoCommand
{
protected override int Execute()
{
var result = CreateExecutor().GetContextInfo(Context.Value());
var result = CreateExecutor().GetContextInfo(Context.Value(), RemainingArguments);

if (_json.HasValue())
{
Expand Down
3 changes: 2 additions & 1 deletion src/ef/Commands/DbContextScaffoldCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ protected override int Execute()
_tables.Values,
_dataAnnotations.HasValue(),
_force.HasValue(),
_useDatabaseNames.HasValue());
_useDatabaseNames.HasValue(),
RemainingArguments);
if (_json.HasValue())
{
ReportJsonResults(result);
Expand Down
2 changes: 1 addition & 1 deletion src/ef/Commands/DbContextScriptCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal partial class DbContextScriptCommand
protected override int Execute()
{
var sql = CreateExecutor().ScriptDbContext(
Context.Value());
Context.Value(), RemainingArguments);

if (!_output.HasValue())
{
Expand Down
2 changes: 1 addition & 1 deletion src/ef/Commands/MigrationsAddCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ protected override void Validate()

protected override int Execute()
{
var files = CreateExecutor().AddMigration(_name.Value, _outputDir.Value(), Context.Value());
var files = CreateExecutor().AddMigration(_name.Value, _outputDir.Value(), Context.Value(), RemainingArguments);

if (_json.HasValue())
{
Expand Down
3 changes: 2 additions & 1 deletion src/ef/Commands/MigrationsListCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ internal partial class MigrationsListCommand
{
protected override int Execute()
{
var migrations = CreateExecutor().GetMigrations(Context.Value()).ToList();
var migrations = CreateExecutor()
.GetMigrations(Context.Value(), RemainingArguments).ToList();

if (_json.HasValue())
{
Expand Down
2 changes: 1 addition & 1 deletion src/ef/Commands/MigrationsRemoveCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal partial class MigrationsRemoveCommand
{
protected override int Execute()
{
var result = CreateExecutor().RemoveMigration(Context.Value(), _force.HasValue());
var result = CreateExecutor().RemoveMigration(Context.Value(), _force.HasValue(), RemainingArguments);
if (_json.HasValue())
{
ReportJsonResults(result);
Expand Down
3 changes: 2 additions & 1 deletion src/ef/Commands/MigrationsScriptCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ protected override int Execute()
_from.Value,
_to.Value,
_idempotent.HasValue(),
Context.Value());
Context.Value(),
RemainingArguments);

if (!_output.HasValue())
{
Expand Down
19 changes: 10 additions & 9 deletions src/ef/IOperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace Microsoft.EntityFrameworkCore.Tools
{
internal interface IOperationExecutor : IDisposable
{
IDictionary AddMigration(string name, string outputDir, string contextType);
IDictionary RemoveMigration(string contextType, bool force);
IEnumerable<IDictionary> GetMigrations(string contextType);
void DropDatabase(string contextType);
IDictionary GetContextInfo(string name);
void UpdateDatabase(string migration, string connectionString, string contextType);
IDictionary AddMigration(string name, string outputDir, string contextType, string[] remainingArguments);
IDictionary RemoveMigration(string contextType, bool force, string[] remainingArguments);
IEnumerable<IDictionary> GetMigrations(string contextType, string[] remainingArguments);
void DropDatabase(string contextType, string[] remainingArguments);
IDictionary GetContextInfo(string name, string[] remainingArguments);
void UpdateDatabase(string migration, string connectionString, string contextType, string[] remainingArguments);
IEnumerable<IDictionary> GetContextTypes();

IDictionary ScaffoldContext(
Expand All @@ -27,10 +27,11 @@ IDictionary ScaffoldContext(
IEnumerable<string> tableFilters,
bool useDataAnnotations,
bool overwriteFiles,
bool useDatabaseNames);
bool useDatabaseNames,
string[] remainingArguments);

string ScriptMigration(string fromMigration, string toMigration, bool idempotent, string contextType);
string ScriptMigration(string fromMigration, string toMigration, bool idempotent, string contextType, string[] remainingArguments);

string ScriptDbContext(string contextType);
string ScriptDbContext(string contextType, string[] remainingArguments);
}
}
49 changes: 30 additions & 19 deletions src/ef/OperationExecutorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,39 +82,46 @@ private object InvokeOperationImpl(string operationName, IDictionary arguments)
return resultHandler.Result;
}

public IDictionary AddMigration(string name, string outputDir, string contextType)
public IDictionary AddMigration(string name, string outputDir, string contextType, string[] remainingArguments)
=> InvokeOperation<IDictionary>(
"AddMigration",
new Dictionary<string, string> { ["name"] = name, ["outputDir"] = outputDir, ["contextType"] = contextType });
new Dictionary<string, object>
{
["name"] = name,
["outputDir"] = outputDir,
["contextType"] = contextType,
["appArgs"] = remainingArguments
});

public IDictionary RemoveMigration(string contextType, bool force)
public IDictionary RemoveMigration(string contextType, bool force, string[] remainingArguments)
=> InvokeOperation<IDictionary>(
"RemoveMigration",
new Dictionary<string, object> { ["contextType"] = contextType, ["force"] = force });
new Dictionary<string, object> { ["contextType"] = contextType, ["force"] = force, ["appArgs"] = remainingArguments });

public IEnumerable<IDictionary> GetMigrations(string contextType)
public IEnumerable<IDictionary> GetMigrations(string contextType, string[] remainingArguments)
=> InvokeOperation<IEnumerable<IDictionary>>(
"GetMigrations",
new Dictionary<string, object> { ["contextType"] = contextType });
new Dictionary<string, object> { ["contextType"] = contextType, ["appArgs"] = remainingArguments });

public void DropDatabase(string contextType)
public void DropDatabase(string contextType, string[] remainingArguments)
=> InvokeOperation(
"DropDatabase",
new Dictionary<string, object> { ["contextType"] = contextType });
new Dictionary<string, object> { ["contextType"] = contextType, ["appArgs"] = remainingArguments });

public IDictionary GetContextInfo(string name)
public IDictionary GetContextInfo(string name, string[] remainingArguments)
=> InvokeOperation<IDictionary>(
"GetContextInfo",
new Dictionary<string, object> { ["contextType"] = name });
new Dictionary<string, object> { ["contextType"] = name, ["appArgs"] = remainingArguments });

public void UpdateDatabase(string migration, string connectionString, string contextType)
public void UpdateDatabase(string migration, string connectionString, string contextType, string[] remainingArguments)
=> InvokeOperation(
"UpdateDatabase",
new Dictionary<string, string>
new Dictionary<string, object>
{
["targetMigration"] = migration,
["connectionString"] = connectionString,
["contextType"] = contextType
["contextType"] = contextType,
["appArgs"] = remainingArguments
});

public IEnumerable<IDictionary> GetContextTypes()
Expand All @@ -130,7 +137,8 @@ public IDictionary ScaffoldContext(
IEnumerable<string> tableFilters,
bool useDataAnnotations,
bool overwriteFiles,
bool useDatabaseNames)
bool useDatabaseNames,
string[] remainingArguments)
=> InvokeOperation<IDictionary>(
"ScaffoldContext",
new Dictionary<string, object>
Expand All @@ -144,27 +152,30 @@ public IDictionary ScaffoldContext(
["tableFilters"] = tableFilters,
["useDataAnnotations"] = useDataAnnotations,
["overwriteFiles"] = overwriteFiles,
["useDatabaseNames"] = useDatabaseNames
["useDatabaseNames"] = useDatabaseNames,
["appArgs"] = remainingArguments
});

public string ScriptMigration(
string fromMigration,
string toMigration,
bool idempotent,
string contextType)
string contextType,
string[] remainingArguments)
=> InvokeOperation<string>(
"ScriptMigration",
new Dictionary<string, object>
{
["fromMigration"] = fromMigration,
["toMigration"] = toMigration,
["idempotent"] = idempotent,
["contextType"] = contextType
["contextType"] = contextType,
["appArgs"] = remainingArguments
});

public string ScriptDbContext(string contextType)
public string ScriptDbContext(string contextType, string[] remainingArguments)
=> InvokeOperation<string>(
"ScriptDbContext",
new Dictionary<string, object> { ["contextType"] = contextType });
new Dictionary<string, object> { ["contextType"] = contextType, ["appArgs"] = remainingArguments });
}
}
28 changes: 28 additions & 0 deletions test/EFCore.Design.Tests/Design/DbContextActivatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,40 @@ public void CreateInstance_works()
Assert.IsType<TestContext>(result);
}

[ConditionalFact]
public void CreateInstance_can_pass_in_arguments()
{
var result = DbContextActivator.CreateInstance(
typeof(ArgsContext), arguments: new string[] { "Pass", "Me", "In" });

Assert.IsType<ArgsContext>(result);
Assert.Collection<string>(((ArgsContext)result).Args,
s => { Assert.Equal("Pass", s); },
s => { Assert.Equal("Me", s); },
s => { Assert.Equal("In", s); });
}

private class TestContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options
.EnableServiceProviderCaching(false)
.UseInMemoryDatabase(nameof(DbContextActivatorTest));
}

private class ArgsContext : DbContext
{
public string[] Args { get; set; }

public ArgsContext(string[] args)
{
Args = args;
}

protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options
.EnableServiceProviderCaching(false)
.UseInMemoryDatabase(nameof(DbContextActivatorTest));
}
}
}

0 comments on commit f7216b3

Please sign in to comment.