Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .NET Core CLI commands #4381

Merged
merged 1 commit into from
Feb 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions EntityFramework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.EntityFrameworkCo
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.EntityFrameworkCore.Sqlite.Design.Tests", "test\Microsoft.EntityFrameworkCore.Sqlite.Design.Tests\Microsoft.EntityFrameworkCore.Sqlite.Design.Tests.xproj", "{BFF1BBE8-C6CE-4103-9C75-6184C8B8D936}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-ef", "src\dotnet-ef\dotnet-ef.xproj", "{5C1B3280-F11D-4E4E-81B3-BCDA4942E097}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-ef.Tests", "test\dotnet-ef.Tests\dotnet-ef.Tests.xproj", "{93D7AB4E-2E04-4217-BBE5-43EC0D54344F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -199,6 +203,14 @@ Global
{BFF1BBE8-C6CE-4103-9C75-6184C8B8D936}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFF1BBE8-C6CE-4103-9C75-6184C8B8D936}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFF1BBE8-C6CE-4103-9C75-6184C8B8D936}.Release|Any CPU.Build.0 = Release|Any CPU
{5C1B3280-F11D-4E4E-81B3-BCDA4942E097}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C1B3280-F11D-4E4E-81B3-BCDA4942E097}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C1B3280-F11D-4E4E-81B3-BCDA4942E097}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C1B3280-F11D-4E4E-81B3-BCDA4942E097}.Release|Any CPU.Build.0 = Release|Any CPU
{93D7AB4E-2E04-4217-BBE5-43EC0D54344F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93D7AB4E-2E04-4217-BBE5-43EC0D54344F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93D7AB4E-2E04-4217-BBE5-43EC0D54344F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93D7AB4E-2E04-4217-BBE5-43EC0D54344F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -235,5 +247,7 @@ Global
{D4A29871-788D-4EA3-B637-1F8D14DA23B4} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
{000FF28B-AA1E-4DD2-8582-0259CF07B025} = {E7D68B03-3A5D-4710-9A1F-20D198E41F78}
{BFF1BBE8-C6CE-4103-9C75-6184C8B8D936} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
{5C1B3280-F11D-4E4E-81B3-BCDA4942E097} = {E7D68B03-3A5D-4710-9A1F-20D198E41F78}
{93D7AB4E-2E04-4217-BBE5-43EC0D54344F} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
Expand All @@ -24,23 +25,23 @@ public class DatabaseOperations

public DatabaseOperations(
[NotNull] ILoggerProvider loggerProvider,
[NotNull] string assemblyName,
[NotNull] string startupAssemblyName,
[NotNull] Assembly assembly,
[NotNull] Assembly startupAssembly,
[CanBeNull] string environment,
[NotNull] string projectDir,
[NotNull] string rootNamespace)
{
Check.NotNull(loggerProvider, nameof(loggerProvider));
Check.NotEmpty(assemblyName, nameof(assemblyName));
Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName));
Check.NotNull(assembly, nameof(assembly));
Check.NotNull(startupAssembly, nameof(startupAssembly));
Check.NotNull(projectDir, nameof(projectDir));
Check.NotNull(rootNamespace, nameof(rootNamespace));

_loggerProvider = loggerProvider;
_projectDir = projectDir;
_rootNamespace = rootNamespace;

var startup = new StartupInvoker(startupAssemblyName, environment);
var startup = new StartupInvoker(startupAssembly, environment);
_servicesBuilder = new DesignTimeServicesBuilder(startup);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,32 @@ namespace Microsoft.EntityFrameworkCore.Design
public class DbContextOperations
{
private readonly ILoggerProvider _loggerProvider;
private readonly string _assemblyName;
private readonly string _startupAssemblyName;
private readonly Assembly _assembly;
private readonly Assembly _startupAssembly;
private readonly string _projectDir;
private readonly LazyRef<ILogger> _logger;
private readonly IServiceProvider _runtimeServices;
private readonly DesignTimeServicesBuilder _servicesBuilder;

public DbContextOperations(
[NotNull] ILoggerProvider loggerProvider,
[NotNull] string assemblyName,
[NotNull] string startupAssemblyName,
[NotNull] Assembly assembly,
[NotNull] Assembly startupAssembly,
[NotNull] string projectDir,
[CanBeNull] string environment)
{
Check.NotNull(loggerProvider, nameof(loggerProvider));
Check.NotEmpty(assemblyName, nameof(assemblyName));
Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName));
Check.NotNull(assembly, nameof(assembly));
Check.NotNull(startupAssembly, nameof(startupAssembly));
Check.NotEmpty(projectDir, nameof(projectDir));

_loggerProvider = loggerProvider;
_assemblyName = assemblyName;
_startupAssemblyName = startupAssemblyName;
_assembly = assembly;
_startupAssembly = startupAssembly;
_projectDir = projectDir;
_logger = new LazyRef<ILogger>(() => _loggerProvider.CreateCommandsLogger());

var startup = new StartupInvoker(startupAssemblyName, environment);
var startup = new StartupInvoker(startupAssembly, environment);
_runtimeServices = startup.ConfigureServices();

_servicesBuilder = new DesignTimeServicesBuilder(startup);
Expand Down Expand Up @@ -125,11 +125,10 @@ private IDictionary<Type, Func<DbContext>> FindContextTypes()
{
_logger.Value.LogDebug(CommandsStrings.LogFindingContexts);

var startupAssembly = Assembly.Load(new AssemblyName(_startupAssemblyName));
var contexts = new Dictionary<Type, Func<DbContext>>();

// Look for IDbContextFactory implementations
var contextFactories = startupAssembly.GetConstructibleTypes()
var contextFactories = _startupAssembly.GetConstructibleTypes()
.Where(t => typeof(IDbContextFactory<DbContext>).GetTypeInfo().IsAssignableFrom(t));
foreach (var factory in contextFactories)
{
Expand Down Expand Up @@ -157,18 +156,8 @@ where i.GetTypeInfo().IsGenericType
}

// Look for DbContext classes in assemblies
Assembly assembly;
try
{
assembly = Assembly.Load(new AssemblyName(_assemblyName));
}
catch (Exception ex)
{
throw new OperationException(CommandsStrings.UnreferencedAssembly(_assemblyName, _startupAssemblyName), ex);
}

var types = startupAssembly.GetConstructibleTypes()
.Concat(assembly.GetConstructibleTypes())
var types = _startupAssembly.GetConstructibleTypes()
.Concat(_assembly.GetConstructibleTypes())
.Select(i => i.AsType());
var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t))
.Concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ public class StartupInvoker
private readonly string _environment;

public StartupInvoker(
[NotNull] string startupAssemblyName,
[NotNull] Assembly startupAssembly,
[CanBeNull] string environment)
{
Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName));
Check.NotNull(startupAssembly, nameof(startupAssembly));

_environment = !string.IsNullOrEmpty(environment)
? environment
: "Development";

var startupAssembly = Assembly.Load(new AssemblyName(startupAssemblyName));
_startupType = startupAssembly.DefinedTypes.Where(t => t.Name == "Startup" + _environment)
.Concat(startupAssembly.DefinedTypes.Where(t => t.Name == "Startup"))
.Concat(startupAssembly.DefinedTypes.Where(t => t.Name == "Program"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ public class MigrationsOperations
{
private readonly ILoggerProvider _loggerProvider;
private readonly LazyRef<ILogger> _logger;
private readonly string _assemblyName;
private readonly Assembly _assembly;
private readonly string _projectDir;
private readonly string _rootNamespace;
private readonly DesignTimeServicesBuilder _servicesBuilder;
private readonly DbContextOperations _contextOperations;

public MigrationsOperations(
[NotNull] ILoggerProvider loggerProvider,
[NotNull] string assemblyName,
[NotNull] string startupAssemblyName,
[NotNull] Assembly assembly,
[NotNull] Assembly startupAssembly,
[CanBeNull] string environment,
[NotNull] string projectDir,
[NotNull] string rootNamespace)
{
Check.NotNull(loggerProvider, nameof(loggerProvider));
Check.NotEmpty(assemblyName, nameof(assemblyName));
Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName));
Check.NotNull(assembly, nameof(assembly));
Check.NotNull(startupAssembly, nameof(startupAssembly));
Check.NotNull(projectDir, nameof(projectDir));
Check.NotNull(rootNamespace, nameof(rootNamespace));

Expand All @@ -48,17 +48,17 @@ public MigrationsOperations(

_loggerProvider = loggerProvider;
_logger = new LazyRef<ILogger>(() => loggerFactory.CreateCommandsLogger());
_assemblyName = assemblyName;
_assembly = assembly;
_projectDir = projectDir;
_rootNamespace = rootNamespace;
_contextOperations = new DbContextOperations(
loggerProvider,
assemblyName,
startupAssemblyName,
assembly,
startupAssembly,
projectDir,
environment);

var startup = new StartupInvoker(startupAssemblyName, environment);
var startup = new StartupInvoker(startupAssembly, environment);
_servicesBuilder = new DesignTimeServicesBuilder(startup);
}

Expand Down Expand Up @@ -162,13 +162,16 @@ private void EnsureServices(IServiceProvider services)
throw new OperationException(CommandsStrings.NonRelationalProvider(providerServices.InvariantName));
}

var assemblyName = _assembly.GetName();
var options = services.GetRequiredService<IDbContextOptions>();
var contextType = services.GetRequiredService<DbContext>().GetType();
var assemblyName = RelationalOptionsExtension.Extract(options).MigrationsAssembly
var migrationsAssemblyName = RelationalOptionsExtension.Extract(options).MigrationsAssembly
?? contextType.GetTypeInfo().Assembly.GetName().Name;
if (_assemblyName != assemblyName)
if (assemblyName.Name != migrationsAssemblyName
&& assemblyName.FullName != migrationsAssemblyName)
{
throw new OperationException(CommandsStrings.MigrationsAssemblyMismatch(_assemblyName, assemblyName));
throw new OperationException(
CommandsStrings.MigrationsAssemblyMismatch(assemblyName.Name, migrationsAssemblyName));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Internal;
Expand Down Expand Up @@ -34,25 +35,37 @@ public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args
var projectDir = (string)args["projectDir"];
var rootNamespace = (string)args["rootNamespace"];

var startupAssembly = Assembly.Load(new AssemblyName(startupTargetName));

Assembly assembly;
try
{
assembly = Assembly.Load(new AssemblyName(targetName));
}
catch (Exception ex)
{
throw new OperationException(CommandsStrings.UnreferencedAssembly(targetName, startupTargetName), ex);
}

_contextOperations = new LazyRef<DbContextOperations>(
() => new DbContextOperations(
loggerProvider,
targetName,
startupTargetName,
assembly,
startupAssembly,
projectDir, environment));
_databaseOperations = new LazyRef<DatabaseOperations>(
() => new DatabaseOperations(
loggerProvider,
targetName,
startupTargetName,
assembly,
startupAssembly,
environment,
projectDir,
rootNamespace));
_migrationsOperations = new LazyRef<MigrationsOperations>(
() => new MigrationsOperations(
loggerProvider,
targetName,
startupTargetName,
assembly,
startupAssembly,
environment,
projectDir,
rootNamespace));
Expand Down Expand Up @@ -318,7 +331,7 @@ private IEnumerable<string> ReverseEngineerImpl(

public class ScaffoldRuntimeDirectives : OperationBase
{
public ScaffoldRuntimeDirectives([NotNull] OperationExecutor executor, [NotNull] object resultHandler, [NotNull] IDictionary args)
public ScaffoldRuntimeDirectives([NotNull] OperationExecutor executor, [NotNull] object resultHandler, [NotNull] IDictionary args)
: base(resultHandler)
{
Check.NotNull(executor, nameof(executor));
Expand Down
32 changes: 32 additions & 0 deletions src/dotnet-ef/ConsoleCommandLogger.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 Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.DotNet.Cli.Utils;
using JetBrains.Annotations;

namespace Microsoft.EntityFrameworkCore.Commands
{
public class ConsoleCommandLogger : CommandLogger
{
public ConsoleCommandLogger([NotNull] string name)
: base(name)
{
}

protected override void WriteDebug(string message)
=> Reporter.Verbose.WriteLine(message.Bold().Black());

protected override void WriteError(string message)
=> Reporter.Error.WriteLine(message.Bold().Red());

protected override void WriteInformation(string message)
=> Reporter.Error.WriteLine(message);

protected override void WriteTrace(string message)
=> Reporter.Verbose.WriteLine(message.Bold().Black());

protected override void WriteWarning(string message)
=> Reporter.Error.WriteLine(message.Bold().Yellow());
}
}
22 changes: 22 additions & 0 deletions src/dotnet-ef/DatabaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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 JetBrains.Annotations;
using Microsoft.Extensions.CommandLineUtils;

namespace Microsoft.EntityFrameworkCore.Commands
{
public class DatabaseCommand
{
public static void Configure([NotNull] CommandLineApplication command)
{
command.Description = "Commands to manage your database";

command.HelpOption("-h|--help");

command.Command("update", DatabaseUpdateCommand.Configure);

command.OnExecute(() => command.ShowHelp());
}
}
}
43 changes: 43 additions & 0 deletions src/dotnet-ef/DatabaseUpdateCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 JetBrains.Annotations;
using Microsoft.Extensions.CommandLineUtils;

namespace Microsoft.EntityFrameworkCore.Commands
{
public class DatabaseUpdateCommand
{
public static void Configure([NotNull] CommandLineApplication command)
{
command.Description = "Updates the database to a specified migration";

var migration = command.Argument(
"[migration]",
"The target migration. If '0', all migrations will be reverted. If omitted, all pending migrations will be applied");

var context = command.Option(
"-c|--context <context>",
"The DbContext to use. If omitted, the default DbContext is used");
var startupProject = command.Option(
"-s|--startupProject <project>",
"The startup project to use. If omitted, the current project is used.");
var environment = command.Option(
"-e|--environment <environment>",
"The environment to use. If omitted, \"Development\" is used.");
command.HelpOption("-h|--help");

command.OnExecute(
() => Execute(migration.Value, context.Value(), startupProject.Value(), environment.Value()));
}

private static int Execute(string migration, string context, string startupProject, string environment)
{
new OperationsFactory(startupProject, environment)
.CreateMigrationsOperations()
.UpdateDatabase(migration, context);

return 0;
}
}
}
Loading