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

Generate DbContext Class in a Different Location #10356

Merged
merged 2 commits into from
Jan 19, 2018
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
1 change: 1 addition & 0 deletions EFCore.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Converters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -51,6 +52,7 @@ public static IServiceCollection AddEntityFrameworkDesignTimeServices(
.AddSingleton<ModelCodeGeneratorDependencies>()
.AddSingleton<ProviderCodeGeneratorDependencies>()
.AddSingleton<RelationalTypeMapperDependencies>()
.AddSingleton<ValueConverterSelectorDependencies>()
.AddSingleton<ICandidateNamingService, CandidateNamingService>()
.AddSingleton<ICSharpDbContextGenerator, CSharpDbContextGenerator>()
.AddSingleton<ICSharpEntityTypeGenerator, CSharpEntityTypeGenerator>()
Expand All @@ -70,6 +72,7 @@ public static IServiceCollection AddEntityFrameworkDesignTimeServices(
.AddSingleton<IReverseEngineerScaffolder, ReverseEngineerScaffolder>()
.AddSingleton<IScaffoldingModelFactory, RelationalScaffoldingModelFactory>()
.AddSingleton<IScaffoldingTypeMapper, ScaffoldingTypeMapper>()
.AddSingleton<IValueConverterSelector, ValueConverterSelector>()
.AddTransient<MigrationsScaffolderDependencies>()
.AddTransient<IMigrationsScaffolder, MigrationsScaffolder>()
.AddTransient<ISnapshotModelProcessor, SnapshotModelProcessor>()
Expand Down
34 changes: 34 additions & 0 deletions src/EFCore.Design/Design/Internal/DatabaseOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public virtual ModelFiles ScaffoldContext(
[NotNull] string provider,
[NotNull] string connectionString,
[CanBeNull] string outputDir,
[CanBeNull] string outputContextDir,
[CanBeNull] string dbContextClassName,
[NotNull] IEnumerable<string> schemas,
[NotNull] IEnumerable<string> tables,
Expand All @@ -81,12 +82,21 @@ public virtual ModelFiles ScaffoldContext(
@namespace += "." + subNamespace;
}

var absoluteOutputDir = outputDir != null
? Path.GetFullPath(Path.Combine(_projectDir, outputDir))
: _projectDir;
var absoluteContextDir = outputContextDir != null
? Path.GetFullPath(Path.Combine(_projectDir, outputContextDir))
: absoluteOutputDir;
var relativeContextDir = MakeDirRelative(absoluteOutputDir, absoluteContextDir);

var scaffoldedModel = scaffolder.ScaffoldModel(
connectionString,
tables,
schemas,
@namespace,
_language,
relativeContextDir,
dbContextClassName,
useDataAnnotations,
useDatabaseNames);
Expand Down Expand Up @@ -124,5 +134,29 @@ private string SubnamespaceFromOutputPath(string projectDir, string outputDir)
? string.Join(".", subPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries))
: null;
}

private static string MakeDirRelative(string root, string path)
{
var relativeUri = new Uri(NormalizeDir(root)).MakeRelativeUri(new Uri(NormalizeDir(path)));

return Uri.UnescapeDataString(relativeUri.ToString()).Replace('/', Path.DirectorySeparatorChar);
}

private static string NormalizeDir(string path)
{
if (string.IsNullOrEmpty(path))
{
return path;
}

var last = path[path.Length - 1];
if (last == Path.DirectorySeparatorChar
|| last == Path.AltDirectorySeparatorChar)
{
return path;
}

return path + Path.DirectorySeparatorChar;
}
}
}
16 changes: 13 additions & 3 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ public class ScaffoldContext : OperationBase
/// <para><c>connectionString</c>--The connection string to the database.</para>
/// <para><c>provider</c>--The provider to use.</para>
/// <para><c>outputDir</c>--The directory to put files in. Paths are relative to the project directory.</para>
/// <para><c>outputDbContextDir</c>--The directory to put DbContext file in. Paths are relative to the project directory.</para>
/// <para><c>dbContextClassName</c>--The name of the DbContext to generate.</para>
/// <para><c>schemaFilters</c>--The schemas of tables to generate entity types for.</para>
/// <para><c>tableFilters</c>--The tables to generate entity types for.</para>
Expand All @@ -427,6 +428,7 @@ public ScaffoldContext([NotNull] OperationExecutor executor, [NotNull] object re
var connectionString = (string)args["connectionString"];
var provider = (string)args["provider"];
var outputDir = (string)args["outputDir"];
var outputDbContextDir = (string)args["outputDbContextDir"];
var dbContextClassName = (string)args["dbContextClassName"];
var schemaFilters = (IEnumerable<string>)args["schemaFilters"];
var tableFilters = (IEnumerable<string>)args["tableFilters"];
Expand All @@ -436,8 +438,7 @@ public ScaffoldContext([NotNull] OperationExecutor executor, [NotNull] object re

Execute(
() => executor.ScaffoldContextImpl(
provider,
connectionString, outputDir, dbContextClassName,
provider, connectionString, outputDir, outputDbContextDir, dbContextClassName,
schemaFilters, tableFilters, useDataAnnotations, overwriteFiles, useDatabaseNames));
}
}
Expand All @@ -446,6 +447,7 @@ private IDictionary ScaffoldContextImpl(
[NotNull] string provider,
[NotNull] string connectionString,
[CanBeNull] string outputDir,
[CanBeNull] string outputDbContextDir,
[CanBeNull] string dbContextClassName,
[NotNull] IEnumerable<string> schemaFilters,
[NotNull] IEnumerable<string> tableFilters,
Expand All @@ -464,9 +466,17 @@ private IDictionary ScaffoldContextImpl(
{
outputDir = Path.GetFullPath(Path.Combine(_projectDir, outputDir));
}
if (!string.IsNullOrWhiteSpace(outputDbContextDir))
{
outputDbContextDir = Path.GetFullPath(Path.Combine(_projectDir, outputDbContextDir));
}
else
{
outputDbContextDir = outputDir;
}

var files = _databaseOperations.Value.ScaffoldContext(
provider, connectionString, outputDir, dbContextClassName,
provider, connectionString, outputDir, outputDbContextDir, dbContextClassName,
schemaFilters, tableFilters, useDataAnnotations, overwriteFiles, useDatabaseNames);

return new Hashtable
Expand Down
2 changes: 2 additions & 0 deletions src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ public interface IModelCodeGenerator : ILanguageBasedService
/// </summary>
/// <param name="model"> The model. </param>
/// <param name="namespace"> The namespace. </param>
/// <param name="contextDir"> The directory of the <see cref="DbContext"/>. </param>
/// <param name="contextName"> The name of the <see cref="DbContext"/>. </param>
/// <param name="connectionString"> The connection string. </param>
/// <param name="dataAnnotations"> A value indicating whether to use data annotations. </param>
/// <returns> The generated model. </returns>
ScaffoldedModel GenerateModel(
[NotNull] IModel model,
[NotNull] string @namespace,
[NotNull] string contextDir,
[NotNull] string contextName,
[NotNull] string connectionString,
bool dataAnnotations);
Expand Down
2 changes: 2 additions & 0 deletions src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public interface IReverseEngineerScaffolder
/// <param name="schemas"> A list of schemas to include. Empty to include all schemas. </param>
/// <param name="namespace"> The namespace of the model. </param>
/// <param name="language"> The programming language to scaffold for. </param>
/// <param name="outputDbContextDir"> The DbContext output dirctory. </param>
/// <param name="contextName"> The <see cref="DbContext"/> name. </param>
/// <param name="useDataAnnotations"> True to scaffold data annotations. </param>
/// <param name="useDatabaseNames"> True to use the database schema names directly. </param>
Expand All @@ -29,6 +30,7 @@ ScaffoldedModel ScaffoldModel(
[NotNull] IEnumerable<string> schemas,
[NotNull] string @namespace,
[NotNull] string language,
[CanBeNull] string outputDbContextDir,
[CanBeNull] string contextName,
bool useDataAnnotations,
bool useDatabaseNames);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,7 @@ public CSharpDbContextGenerator(
/// 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 string WriteCode(
IModel model,
string @namespace,
string contextName,
string connectionString,
bool useDataAnnotations)
public virtual string WriteCode(IModel model, string @namespace, string contextName, string connectionString, bool useDataAnnotations)
{
Check.NotNull(model, nameof(model));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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 JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
Expand Down Expand Up @@ -58,12 +59,14 @@ public CSharpModelGenerator(
public override ScaffoldedModel GenerateModel(
IModel model,
string @namespace,
string contextDir,
string contextName,
string connectionString,
bool useDataAnnotations)
{
Check.NotNull(model, nameof(model));
Check.NotEmpty(@namespace, nameof(@namespace));
Check.NotNull(contextDir, nameof(contextDir));
Check.NotEmpty(contextName, nameof(contextName));
Check.NotEmpty(connectionString, nameof(connectionString));

Expand All @@ -73,7 +76,7 @@ public override ScaffoldedModel GenerateModel(

// output DbContext .cs file
var dbContextFileName = contextName + FileExtension;
resultingFiles.ContextFile = new ScaffoldedFile { Path = dbContextFileName, Code = generatedCode };
resultingFiles.ContextFile = new ScaffoldedFile { Path = Path.Combine(contextDir, dbContextFileName), Code = generatedCode };

foreach (var entityType in model.GetEntityTypes())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public virtual ScaffoldedModel ScaffoldModel(
IEnumerable<string> schemas,
string @namespace,
string language,
string outputDbContextDir,
string contextName,
bool useDataAnnotations,
bool useDatabaseNames)
Expand Down Expand Up @@ -107,7 +108,7 @@ public virtual ScaffoldedModel ScaffoldModel(

var codeGenerator = ModelCodeGeneratorSelector.Select(language);

return codeGenerator.GenerateModel(model, @namespace, contextName, connectionString, useDataAnnotations);
return codeGenerator.GenerateModel(model, @namespace, outputDbContextDir ?? string.Empty, contextName, connectionString, useDataAnnotations);
}

/// <summary>
Expand All @@ -131,7 +132,8 @@ public virtual ModelFiles Save(
var files = new ModelFiles();
Directory.CreateDirectory(outputDir);

var contextPath = Path.Combine(outputDir, scaffoldedModel.ContextFile.Path);
var contextPath = Path.GetFullPath(Path.Combine(outputDir, scaffoldedModel.ContextFile.Path));
Directory.CreateDirectory(Path.GetDirectoryName(contextPath));
File.WriteAllText(contextPath, scaffoldedModel.ContextFile.Code, Encoding.UTF8);
files.ContextFile = contextPath;

Expand Down
2 changes: 2 additions & 0 deletions src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ public ModelCodeGenerator([NotNull] ModelCodeGeneratorDependencies dependencies)
/// </summary>
/// <param name="model"> The model. </param>
/// <param name="namespace"> The namespace. </param>
/// <param name="contextDir"> The directory of the <see cref="DbContext"/>. </param>
/// <param name="contextName"> The name of the <see cref="DbContext"/>. </param>
/// <param name="connectionString"> The connection string. </param>
/// <param name="dataAnnotations"> A value indicating whether to use data annotations. </param>
/// <returns> The generated model. </returns>
public abstract ScaffoldedModel GenerateModel(
IModel model,
string @namespace,
string contextDir,
string contextName,
string connectionString,
bool dataAnnotations);
Expand Down
10 changes: 10 additions & 0 deletions src/EFCore.Tools/tools/EntityFrameworkCore.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Register-TabExpansion Scaffold-DbContext @{
Project = { GetProjects }
StartupProject = { GetProjects }
OutputDir = { <# Disabled. Otherwise, paths would be relative to the solution directory. #> }
OutputDbContextDir = { <# Disabled. Otherwise, paths would be relative to the solution directory. #> }
}

<#
Expand All @@ -277,6 +278,9 @@ Register-TabExpansion Scaffold-DbContext @{
.PARAMETER OutputDir
The directory to put files in. Paths are relative to the project directory.

.PARAMETER OutputDbContextDir
The directory to put DbContext file in. Paths are relative to the project directory.

.PARAMETER Context
The name of the DbContext to generate.

Expand Down Expand Up @@ -313,6 +317,7 @@ function Scaffold-DbContext
[Parameter(Position = 1, Mandatory = $true)]
[string] $Provider,
[string] $OutputDir,
[string] $OutputDbContextDir,
[string] $Context,
[string[]] $Schemas = @(),
[string[]] $Tables = @(),
Expand All @@ -331,6 +336,11 @@ function Scaffold-DbContext
{
$params += '--output-dir', $OutputDir
}

if ($OutputDbContextDir)
{
$params += '--output-dbcontext-dir', $OutputDbContextDir
}

if ($Context)
{
Expand Down
6 changes: 6 additions & 0 deletions src/dotnet-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/dotnet-ef/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,7 @@
<data name="MigrationsRemoveRevertDescription" xml:space="preserve">
<value>Revert the migration if it has been applied to the database.</value>
</data>
<data name="OutputDbContextDirDescription" xml:space="preserve">
<value>The directory to put DbContext file in. Paths are relative to the project directory.</value>
</data>
</root>
2 changes: 2 additions & 0 deletions src/ef/Commands/DbContextScaffoldCommand.Configure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal partial class DbContextScaffoldCommand : ProjectCommandBase
private CommandOption _context;
private CommandOption _force;
private CommandOption _outputDir;
private CommandOption _outputDbContextDir;
private CommandOption _schemas;
private CommandOption _tables;
private CommandOption _useDatabaseNames;
Expand All @@ -30,6 +31,7 @@ public override void Configure(CommandLineApplication command)
_context = command.Option("-c|--context <NAME>", Resources.ContextNameDescription);
_force = command.Option("-f|--force", Resources.DbContextScaffoldForceDescription);
_outputDir = command.Option("-o|--output-dir <PATH>", Resources.OutputDirDescription);
_outputDbContextDir = command.Option("--output-dbcontext-dir <PATH>", Resources.OutputDbContextDirDescription);
_schemas = command.Option("--schema <SCHEMA_NAME>...", Resources.SchemasDescription);
_tables = command.Option("-t|--table <TABLE_NAME>...", Resources.TablesDescription);
_useDatabaseNames = command.Option("--use-database-names", Resources.UseDatabaseNamesDescription);
Expand Down
1 change: 1 addition & 0 deletions src/ef/Commands/DbContextScaffoldCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ protected override int Execute()
_provider.Value,
_connection.Value,
_outputDir.Value(),
_outputDbContextDir.Value(),
_context.Value(),
_schemas.Values,
_tables.Values,
Expand Down
1 change: 1 addition & 0 deletions src/ef/IOperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ IDictionary ScaffoldContext(
string provider,
string connectionString,
string outputDir,
string outputDbContextDir,
string dbContextClassName,
IEnumerable<string> schemaFilters,
IEnumerable<string> tableFilters,
Expand Down
2 changes: 2 additions & 0 deletions src/ef/OperationExecutorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public IDictionary ScaffoldContext(
string provider,
string connectionString,
string outputDir,
string outputDbContextDir,
string dbContextClassName,
IEnumerable<string> schemaFilters,
IEnumerable<string> tableFilters,
Expand All @@ -159,6 +160,7 @@ public IDictionary ScaffoldContext(
["provider"] = provider,
["connectionString"] = connectionString,
["outputDir"] = outputDir,
["outputDbContextDir"] = outputDbContextDir,
["dbContextClassName"] = dbContextClassName,
["schemaFilters"] = schemaFilters,
["tableFilters"] = tableFilters,
Expand Down
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 @@ -312,4 +312,7 @@
<data name="MigrationsRemoveRevertDescription" xml:space="preserve">
<value>Revert the migration if it has been applied to the database.</value>
</data>
<data name="OutputDbContextDirDescription" xml:space="preserve">
<value>The directory to put DbContext file in. Paths are relative to the project directory.</value>
</data>
</root>
Loading