Skip to content

Commit

Permalink
Implements "ef dbcontext script"
Browse files Browse the repository at this point in the history
and PS>Script-DbContext

fixes issue dotnet#10378
  • Loading branch information
ErikEJ committed Apr 21, 2019
1 parent a69d84b commit 8f0c73a
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/EFCore.Design/Design/Internal/DbContextOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ public virtual void DropDatabase([CanBeNull] string contextType)
}
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual string ScriptDbContext([CanBeNull] string contextType)
{
using (var context = CreateContext(contextType))
{
return context.Database.GenerateCreateScript();
}
}

/// <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
Expand Down
31 changes: 31 additions & 0 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,37 @@ public DropDatabase(
private void DropDatabaseImpl(string contextType)
=> _contextOperations.Value.DropDatabase(contextType);

/// <summary>
/// Represents an operation to generate a SQL script from the DbContext.
/// </summary>
public class ScriptDbContext : OperationBase
{
/// <summary>
/// <para>Initializes a new instance of the <see cref="ScriptDbContext" /> class.</para>
/// <para>The arguments supported by <paramref name="args" /> are:</para>
/// <para><c>contextType</c>--The <see cref="DbContext" /> to use.</para>
/// </summary>
/// <param name="executor"> The operation executor. </param>
/// <param name="resultHandler"> The <see cref="IOperationResultHandler" />. </param>
/// <param name="args"> The operation arguments. </param>
public ScriptDbContext(
[NotNull] OperationExecutor executor,
[NotNull] object resultHandler,
[NotNull] IDictionary args)
: base(resultHandler)
{
Check.NotNull(executor, nameof(executor));
Check.NotNull(args, nameof(args));

var contextType = (string)args["contextType"];

Execute(() => executor.ScriptDbContextImpl(contextType));
}
}

private string ScriptDbContextImpl(string contextType)
=> _contextOperations.Value.ScriptDbContext(contextType);

/// <summary>
/// Represents an operation.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/EFCore.Tools/EntityFrameworkCore.PowerShell2.psd1.in
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
'Get-DbContext',
'Remove-Migration',
'Scaffold-DbContext',
'Script-DbContext',
'Script-Migration',
'Update-Database'
)
Expand Down
1 change: 1 addition & 0 deletions src/EFCore.Tools/EntityFrameworkCore.psd1.in
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
'Get-DbContext',
'Remove-Migration',
'Scaffold-DbContext',
'Script-DbContext',
'Script-Migration',
'Update-Database'
)
Expand Down
5 changes: 5 additions & 0 deletions src/EFCore.Tools/tools/EntityFrameworkCore.PowerShell2.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ function Scaffold-DbContext
throw $versionErrorMessage
}

function Script-DbContext
{
throw $versionErrorMessage
}

function Script-Migration
{
throw $versionErrorMessage
Expand Down
71 changes: 71 additions & 0 deletions src/EFCore.Tools/tools/EntityFrameworkCore.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,77 @@ function Scaffold-DbContext
ShowConsole
}

#
# Script-DbContext
#

Register-TabExpansion Script-DbContext @{
Context = { param($x) GetContextTypes $x.Project $x.StartupProject }
Project = { GetProjects }
StartupProject = { GetProjects }
}

<#
.SYNOPSIS
Generates a SQL script from current DbContext.
.DESCRIPTION
Generates a SQL script from current DbContext.
.PARAMETER Output
The file to write the result to.
.PARAMETER Context
The DbContext to use.
.PARAMETER Project
The project to use.
.PARAMETER StartupProject
The startup project to use. Defaults to the solution's startup project.
.LINK
about_EntityFrameworkCore
#>
function Script-DbContext
{
[CmdletBinding(PositionalBinding = $false)]
param(
[string] $Output,
[string] $Context,
[string] $Project,
[string] $StartupProject)

$dteProject = GetProject $Project
$dteStartupProject = GetStartupProject $StartupProject $dteProject

if (!$Output)
{
$intermediatePath = GetIntermediatePath $dteProject
if (![IO.Path]::IsPathRooted($intermediatePath))
{
$projectDir = GetProperty $dteProject.Properties 'FullPath'
$intermediatePath = Join-Path $projectDir $intermediatePath -Resolve | Convert-Path
}

$scriptFileName = [IO.Path]::ChangeExtension([IO.Path]::GetRandomFileName(), '.sql')
$Output = Join-Path $intermediatePath $scriptFileName
}
elseif (![IO.Path]::IsPathRooted($Output))
{
$Output = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Output)
}

$params = 'dbcontext', 'script', '--output', $Output

$params += GetParams $Context

EF $dteProject $dteStartupProject $params

$DTE.ItemOperations.OpenFile($Output) | Out-Null
ShowConsole
}

#
# Script-Migration
#
Expand Down
3 changes: 3 additions & 0 deletions src/EFCore.Tools/tools/about_EntityFrameworkCore.help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ LONG DESCRIPTION

Scaffold-DbContext Scaffolds a DbContext and entity types for a database.

Script-DbContext Generates a SQL script from the current DbContext.

Script-Migration Generates a SQL script from migrations.

Update-Database Updates the database to a specified migration.
Expand All @@ -40,5 +42,6 @@ SEE ALSO
Get-DbContext
Remove-Migration
Scaffold-DbContext
Script-DbContext
Script-Migration
Update-Database
1 change: 1 addition & 0 deletions src/ef/Commands/DbContextCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public override void Configure(CommandLineApplication command)
command.Command("info", new DbContextInfoCommand().Configure);
command.Command("list", new DbContextListCommand().Configure);
command.Command("scaffold", new DbContextScaffoldCommand().Configure);
command.Command("script", new DbContextScriptCommand().Configure);

base.Configure(command);
}
Expand Down
22 changes: 22 additions & 0 deletions src/ef/Commands/DbContextScriptCommand.Configure.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 Microsoft.DotNet.Cli.CommandLine;
using Microsoft.EntityFrameworkCore.Tools.Properties;

namespace Microsoft.EntityFrameworkCore.Tools.Commands
{
internal partial class DbContextScriptCommand : ContextCommandBase
{
private CommandOption _output;

public override void Configure(CommandLineApplication command)
{
command.Description = Resources.MigrationsScriptDescription;

_output = command.Option("-o|--output <FILE>", Resources.OutputDescription);

base.Configure(command);
}
}
}
43 changes: 43 additions & 0 deletions src/ef/Commands/DbContextScriptCommand.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 System.IO;
using System.Text;
using Microsoft.EntityFrameworkCore.Tools.Properties;

namespace Microsoft.EntityFrameworkCore.Tools.Commands
{
// ReSharper disable once ArrangeTypeModifiers
internal partial class DbContextScriptCommand
{
protected override int Execute()
{
var sql = CreateExecutor().ScriptDbContext(
Context.Value());

if (!_output.HasValue())
{
Reporter.WriteData(sql);
}
else
{
var output = _output.Value();
if (WorkingDir.HasValue())
{
output = Path.Combine(WorkingDir.Value(), output);
}

var directory = Path.GetDirectoryName(output);
if (!string.IsNullOrEmpty(directory))
{
Directory.CreateDirectory(directory);
}

Reporter.WriteVerbose(Resources.WritingFile(_output.Value()));
File.WriteAllText(output, sql, Encoding.UTF8);
}

return base.Execute();
}
}
}
2 changes: 2 additions & 0 deletions src/ef/IOperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ IDictionary ScaffoldContext(
bool useDatabaseNames);

string ScriptMigration(string fromMigration, string toMigration, bool idempotent, string contextType);

string ScriptDbContext(string contextType);
}
}
8 changes: 8 additions & 0 deletions src/ef/OperationExecutorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,13 @@ public string ScriptMigration(
["idempotent"] = idempotent,
["contextType"] = contextType
});

public string ScriptDbContext(string contextType)
=> InvokeOperation<string>(
"ScriptDbContext",
new Dictionary<string, object>
{
["contextType"] = contextType
});
}
}
6 changes: 6 additions & 0 deletions src/ef/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/ef/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,7 @@
<data name="WorkingDirDescription" xml:space="preserve">
<value>The working directory of the tool invoking this command.</value>
</data>
<data name="DbContextScriptDescription" xml:space="preserve">
<value>Generate a script to create all tables for the DbContext.</value>
</data>
</root>
21 changes: 21 additions & 0 deletions test/ef.Tests/SimpleProjectTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ public void ScriptMigration()
}
}

[Fact]
public void ScriptDbContext()
{
try
{
var sql = _project.Executor.ScriptDbContext("SimpleContext");
Assert.NotEmpty(sql);
}
catch (WrappedException ex)
{
throw new WrappedXunitException(ex);
}
}

[Fact]
public void GetContextTypes()
{
Expand Down Expand Up @@ -229,6 +243,13 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(""Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=SimpleProject.SimpleContext;Integrated Security=True"");
}
internal DbSet<Simple> Simples { get; set; }
}
internal class Simple
{
public int Id { get; set; }
}
namespace Migrations
Expand Down

0 comments on commit 8f0c73a

Please sign in to comment.