diff --git a/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationException.cs b/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationException.cs index 688b1ea6c47..1af33fdb9e4 100644 --- a/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationException.cs +++ b/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationException.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Design { + /// + /// Represents an exception whose stack trace should, by default, not be reported by the commands. + /// public class OperationException : Exception { public OperationException([NotNull] string message) diff --git a/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationExecutor.cs b/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationExecutor.cs index bbb86a7303d..b5156b8ff6d 100644 --- a/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationExecutor.cs +++ b/src/Microsoft.EntityFrameworkCore.Commands/Design/OperationExecutor.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Design { + /// + /// A version-resilient, AppDomain-and-reflection-friendly facade for command operations. + /// public partial class OperationExecutor { private readonly LazyRef _contextOperations; @@ -124,7 +127,7 @@ public AddMigration( } } - private IEnumerable AddMigrationImpl( + private IDictionary AddMigrationImpl( [NotNull] string name, [CanBeNull] string outputDir, [CanBeNull] string contextType) diff --git a/src/Microsoft.EntityFrameworkCore.Commands/tools/EntityFramework.psm1 b/src/Microsoft.EntityFrameworkCore.Commands/tools/EntityFramework.psm1 index ff1fbded12d..978003aa645 100644 --- a/src/Microsoft.EntityFrameworkCore.Commands/tools/EntityFramework.psm1 +++ b/src/Microsoft.EntityFrameworkCore.Commands/tools/EntityFramework.psm1 @@ -50,7 +50,7 @@ function Use-DbContext { if ($candidates.length -gt 1 -and $exactMatch -is "String") { $candidates = $exactMatch } - + if ($candidates.length -lt 1) { throw "No DbContext named '$Context' was found" } elseif ($candidates.length -gt 1 -and !($candidates -is "String")) { @@ -500,7 +500,7 @@ function Scaffold-DbContext { $artifacts | %{ $dteProject.ProjectItems.AddFromFile($_) | Out-Null } $DTE.ItemOperations.OpenFile($artifacts[0]) | Out-Null - + ShowConsole } } @@ -537,7 +537,7 @@ function GetContextTypes($projectName, $startupProjectName, $environment) { $project = $values.Project if (IsDotNetProject $startupProject) { - $types = InvokeDotNetEf $startupProject -Json dbcontext list + $types = InvokeDotNetEf $startupProject -Json dbcontext list return $types | %{ $_.fullName } } else { $contextTypes = InvokeOperation $startupProject $environment $project GetContextTypes -skipBuild @@ -642,7 +642,7 @@ function InvokeDotNetEf($project, [switch] $Json) { $arguments += "--json" } else { # TODO better json output parsing so we don't need to suppress verbose output - $arguments = ,"--verbose" + $arguments + $arguments = ,"--verbose" + $arguments } $command = "ef $($arguments -join ' ')" try { diff --git a/src/dotnet-ef/CommandException.cs b/src/dotnet-ef/CommandException.cs deleted file mode 100644 index dc3ef7180da..00000000000 --- a/src/dotnet-ef/CommandException.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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; -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Commands -{ - public class CommandException : Exception - { - public CommandException([NotNull] string message) - : base(message) - { - } - } -} diff --git a/src/dotnet-ef/DatabaseDropCommand.cs b/src/dotnet-ef/DatabaseDropCommand.cs index 9c9048e7fa0..2798f8a3ef8 100644 --- a/src/dotnet-ef/DatabaseDropCommand.cs +++ b/src/dotnet-ef/DatabaseDropCommand.cs @@ -35,7 +35,7 @@ public static void Configure([NotNull] CommandLineApplication command) private static int Execute(string context, string startupProject, string environment, bool isForced) { - new OperationExecutor(startupProject, environment) + new ReflectionOperationExecutor(startupProject, environment) .DropDatabase( context, (database, dataSource) => diff --git a/src/dotnet-ef/DatabaseUpdateCommand.cs b/src/dotnet-ef/DatabaseUpdateCommand.cs index 9d05204d128..55a5d6aa2ed 100644 --- a/src/dotnet-ef/DatabaseUpdateCommand.cs +++ b/src/dotnet-ef/DatabaseUpdateCommand.cs @@ -34,7 +34,7 @@ public static void Configure([NotNull] CommandLineApplication command) private static int Execute(string migration, string context, string startupProject, string environment) { - new OperationExecutor(startupProject, environment) + new ReflectionOperationExecutor(startupProject, environment) .UpdateDatabase(migration, context); return 0; diff --git a/src/dotnet-ef/DbContextListCommand.cs b/src/dotnet-ef/DbContextListCommand.cs index a2fff996ea7..d8a37a831ba 100644 --- a/src/dotnet-ef/DbContextListCommand.cs +++ b/src/dotnet-ef/DbContextListCommand.cs @@ -42,7 +42,7 @@ private static int Execute( string environment, Action> reportResultsAction) { - var contextTypes = new OperationExecutor(startupProject, environment) + var contextTypes = new ReflectionOperationExecutor(startupProject, environment) .GetContextTypes(); reportResultsAction(contextTypes); diff --git a/src/dotnet-ef/DbContextScaffoldCommand.cs b/src/dotnet-ef/DbContextScaffoldCommand.cs index 54925731481..ea3e2cca833 100644 --- a/src/dotnet-ef/DbContextScaffoldCommand.cs +++ b/src/dotnet-ef/DbContextScaffoldCommand.cs @@ -96,7 +96,7 @@ private static int Execute( string startupProject, string environment) { - new OperationExecutor(startupProject, environment) + new ReflectionOperationExecutor(startupProject, environment) .ReverseEngineer( provider, connection, diff --git a/src/dotnet-ef/MigrationsAddCommand.cs b/src/dotnet-ef/MigrationsAddCommand.cs index 7449c008b62..b7b24cb0137 100644 --- a/src/dotnet-ef/MigrationsAddCommand.cs +++ b/src/dotnet-ef/MigrationsAddCommand.cs @@ -65,7 +65,7 @@ private static int Execute( string environment, Action reporter) { - var files = new OperationExecutor(startupProject, environment) + var files = new ReflectionOperationExecutor(startupProject, environment) .AddMigration(name, outputDir, context); reporter?.Invoke(files); @@ -79,7 +79,7 @@ private static void ReportJson(IDictionary files) { // TODO use a real json serializer Reporter.Output.WriteLine("{"); - Reporter.Output.WriteLine(" \"MigrationFile\": \""+ SerializePath(files["MigrationFile"] as string) + "\","); + Reporter.Output.WriteLine(" \"MigrationFile\": \"" + SerializePath(files["MigrationFile"] as string) + "\","); Reporter.Output.WriteLine(" \"MetadataFile\": \"" + SerializePath(files["MetadataFile"] as string) + "\","); Reporter.Output.WriteLine(" \"SnapshotFile\": \"" + SerializePath(files["SnapshotFile"] as string) + "\""); Reporter.Output.WriteLine("}"); diff --git a/src/dotnet-ef/MigrationsListCommand.cs b/src/dotnet-ef/MigrationsListCommand.cs index 45bdbff8dc4..e2081b6cda1 100644 --- a/src/dotnet-ef/MigrationsListCommand.cs +++ b/src/dotnet-ef/MigrationsListCommand.cs @@ -47,7 +47,7 @@ private static int Execute( string environment, Action> reportResultsAction) { - var migrations = new OperationExecutor(startupProject, environment) + var migrations = new ReflectionOperationExecutor(startupProject, environment) .GetMigrations(context); reportResultsAction(migrations); diff --git a/src/dotnet-ef/MigrationsRemoveCommand.cs b/src/dotnet-ef/MigrationsRemoveCommand.cs index 6a7f07c61ed..d4443b7a26c 100644 --- a/src/dotnet-ef/MigrationsRemoveCommand.cs +++ b/src/dotnet-ef/MigrationsRemoveCommand.cs @@ -38,7 +38,7 @@ public static void Configure([NotNull] CommandLineApplication command) private static int Execute(string context, string startupProject, string environment, bool force) { - new OperationExecutor(startupProject, environment) + new ReflectionOperationExecutor(startupProject, environment) .RemoveMigration(context, force); return 0; diff --git a/src/dotnet-ef/MigrationsScriptCommand.cs b/src/dotnet-ef/MigrationsScriptCommand.cs index 849b46655ca..0b9c299461e 100644 --- a/src/dotnet-ef/MigrationsScriptCommand.cs +++ b/src/dotnet-ef/MigrationsScriptCommand.cs @@ -59,7 +59,7 @@ private static int Execute( string startupProject, string environment) { - var sql = new OperationExecutor(startupProject, environment) + var sql = new ReflectionOperationExecutor(startupProject, environment) .ScriptMigration(from, to, idempotent, context); if (string.IsNullOrEmpty(output)) diff --git a/src/dotnet-ef/OperationErrorException.cs b/src/dotnet-ef/OperationErrorException.cs new file mode 100644 index 00000000000..e16b5d8ea94 --- /dev/null +++ b/src/dotnet-ef/OperationErrorException.cs @@ -0,0 +1,33 @@ +// 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; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Commands +{ + public class OperationErrorException : Exception + { + public const string OperationException = "Microsoft.EntityFrameworkCore.Design.OperationException"; + + private readonly string _stackTrace; + + public OperationErrorException([NotNull] string type, [NotNull] string stackTrace, [NotNull] string message) + : base(message) + { + _stackTrace = stackTrace; + Type = type; + } + + public virtual string Type { get; } + + public override string ToString() + => _stackTrace; + + public static OperationErrorException CreateOperationException([NotNull] string message) + => new OperationErrorException( + OperationException, + OperationException + ": " + message + Environment.NewLine + Environment.StackTrace, + message); + } +} diff --git a/src/dotnet-ef/Program.cs b/src/dotnet-ef/Program.cs index 84f255aeb2a..b0bf2ce7220 100644 --- a/src/dotnet-ef/Program.cs +++ b/src/dotnet-ef/Program.cs @@ -50,8 +50,7 @@ public static int Main([NotNull] string[] args) ex = ex.InnerException; } - if (!(ex is CommandException - || (ex as OperationException)?.Type == "Microsoft.EntityFrameworkCore.Design.OperationException")) + if ((ex as OperationErrorException)?.Type != OperationErrorException.OperationException) { Reporter.Error.WriteLine(ex.ToString()); } diff --git a/src/dotnet-ef/OperationExecutor.cs b/src/dotnet-ef/ReflectionOperationExecutor.cs similarity index 90% rename from src/dotnet-ef/OperationExecutor.cs rename to src/dotnet-ef/ReflectionOperationExecutor.cs index 3e4fadf3641..f49214be9b3 100644 --- a/src/dotnet-ef/OperationExecutor.cs +++ b/src/dotnet-ef/ReflectionOperationExecutor.cs @@ -16,18 +16,16 @@ namespace Microsoft.EntityFrameworkCore.Commands { - public class OperationExecutor + public class ReflectionOperationExecutor { private const string ExecutorTypeName = "Microsoft.EntityFrameworkCore.Design.OperationExecutor"; + private const string DataDirEnvName = "ADONET_DATA_DIR"; private readonly Assembly _commandsAssembly; private readonly object _executor; private readonly string _startupProjectDir; - private const string DataDirEnvName = "ADONET_DATA_DIR"; - private const string DefaultConfiguration = "Debug"; - - public OperationExecutor([CanBeNull] string startupProject, [CanBeNull] string environment) + public ReflectionOperationExecutor([CanBeNull] string startupProject, [CanBeNull] string environment) { var project = Path.Combine(Directory.GetCurrentDirectory(), Project.FileName); @@ -52,12 +50,12 @@ public OperationExecutor([CanBeNull] string startupProject, [CanBeNull] string e new[] { startupProject, "-f", startupProjectContext.TargetFramework.GetShortFolderName() }); if (buildCommand.Execute().ExitCode != 0) { - throw new CommandException("Build failed."); + throw OperationErrorException.CreateOperationException("Build failed."); } Reporter.Verbose.WriteLine("Build succeeded.".Bold().Black()); - var runtimeOutputPath = startupProjectContext.GetOutputPaths(DefaultConfiguration)?.RuntimeOutputPath; + var runtimeOutputPath = startupProjectContext.GetOutputPaths(Constants.DefaultConfiguration)?.RuntimeOutputPath; if (!string.IsNullOrEmpty(runtimeOutputPath)) { // TODO set data directory in AppDomain when/if this supports desktop .NET @@ -72,8 +70,19 @@ public OperationExecutor([CanBeNull] string startupProject, [CanBeNull] string e var rootNamespace = projectFile.Name; var assemblyLoadContext = startupProjectContext.CreateLoadContext(); - _commandsAssembly = assemblyLoadContext.LoadFromAssemblyName( - new AssemblyName("Microsoft.EntityFrameworkCore.Commands")); + try + { + _commandsAssembly = assemblyLoadContext.LoadFromAssemblyName( + new AssemblyName("Microsoft.EntityFrameworkCore.Commands")); + } + catch (FileNotFoundException ex) + { + Reporter.Verbose.WriteLine(ex.ToString().Bold().Black()); + + throw OperationErrorException.CreateOperationException( + "Cannot execute this command because Microsoft.EntityFramework.Commands is not installed in the " + + "startup project '" + startupAssemblyName + "'."); + } var assemblyLoader = Activator.CreateInstance( _commandsAssembly.GetType( @@ -97,11 +106,12 @@ public OperationExecutor([CanBeNull] string startupProject, [CanBeNull] string e _commandsAssembly.GetType(ExecutorTypeName, throwOnError: true, ignoreCase: false), logHandler, new Dictionary - { + { ["targetName"] = assemblyName, ["startupTargetName"] = startupAssemblyName, ["environment"] = environment, ["projectDir"] = projectDir, + ["startupProjectDir"] = _startupProjectDir, ["rootNamespace"] = rootNamespace }, assemblyLoader); @@ -216,8 +226,8 @@ private ProjectContext GetCompatibleProjectContext(string projectPath) f => new NuGetFramework(f)); if (framework == null) { - throw new CommandException( - "The project '" + projectFile.Name + "' doesn't target a framework compatible with .NET Standard "+ + throw OperationErrorException.CreateOperationException( + "The project '" + projectFile.Name + "' doesn't target a framework compatible with .NET Standard " + "App 1.5. You must target a compatible framework such as 'netstandard1.3' in order to use the " + "Entity Framework .NET Core CLI Commands."); } @@ -260,7 +270,7 @@ private T Execute(string operation, IDictionary args) if (resultHandler.ErrorType != null) { - throw new OperationException( + throw new OperationErrorException( resultHandler.ErrorType, resultHandler.ErrorStackTrace, resultHandler.ErrorMessage); diff --git a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Design/OperationExecutorTest.cs b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Design/OperationExecutorTest.cs index dde004b14b5..6cf4e802b04 100644 --- a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Design/OperationExecutorTest.cs +++ b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Design/OperationExecutorTest.cs @@ -38,7 +38,10 @@ public void GetContextType_works_cross_domain() public void AddMigration_works_cross_domain() { var artifacts = _project.Executor.AddMigration("EmptyMigration", "Migrationz", "SimpleContext"); - Assert.Equal(3, artifacts.Count()); + Assert.NotNull(artifacts); + Assert.NotNull(artifacts["MigrationFile"]); + Assert.NotNull(artifacts["MetadataFile"]); + Assert.NotNull(artifacts["SnapshotFile"]); Assert.True(Directory.Exists(Path.Combine(_project.TargetDir, @"Migrationz"))); } @@ -124,12 +127,12 @@ protected override void Up(MigrationBuilder migrationBuilder) }" } }; var build = source.Build(); - Executor = new OperationExecutorWrapper(TargetDir, build.TargetName, TargetDir, TargetDir, "SimpleProject"); + Executor = new AppDomainOperationExecutor(TargetDir, build.TargetName, TargetDir, TargetDir, "SimpleProject"); } public string TargetDir => _directory.Path; - public OperationExecutorWrapper Executor { get; } + public AppDomainOperationExecutor Executor { get; } public void Dispose() { @@ -219,7 +222,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }" } }; var build = source.Build(); - using (var executor = new OperationExecutorWrapper(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) + using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) { var migrations = executor.GetMigrations("Context1"); @@ -320,7 +323,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }" } }; var migrationsBuild = migrationsSource.Build(); - using (var executor = new OperationExecutorWrapper(targetDir, migrationsBuild.TargetName, targetDir, targetDir, "MyProject")) + using (var executor = new AppDomainOperationExecutor(targetDir, migrationsBuild.TargetName, targetDir, targetDir, "MyProject")) { var contextTypes = executor.GetContextTypes(); @@ -398,10 +401,10 @@ protected override void Up(MigrationBuilder migrationBuilder) }" } }; var build = source.Build(); - using (var executor = new OperationExecutorWrapper(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) + using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) { var artifacts = executor.AddMigration("MyMigration", /*outputDir:*/ null, "MySecondContext"); - Assert.Equal(3, artifacts.Count()); + Assert.Equal(3, artifacts.Keys.Count); Assert.True(Directory.Exists(Path.Combine(targetDir, @"Migrations\MySecond"))); } } @@ -471,9 +474,9 @@ protected override void Up(MigrationBuilder migrationBuilder) }" } }; var build = source.Build(); - using (var executor = new OperationExecutorWrapper(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) + using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) { - var ex = Assert.Throws( + var ex = Assert.Throws( () => executor.GetMigrations("MyContext")); Assert.Equal( @@ -487,9 +490,9 @@ protected override void Up(MigrationBuilder migrationBuilder) public void Assembly_load_errors_are_wrapped() { var targetDir = AppDomain.CurrentDomain.BaseDirectory; - using (var executor = new OperationExecutorWrapper(targetDir, "Unknown", targetDir, targetDir, "Unknown")) + using (var executor = new AppDomainOperationExecutor(targetDir, "Unknown", targetDir, targetDir, "Unknown")) { - Assert.Throws(() => executor.GetContextTypes()); + Assert.Throws(() => executor.GetContextTypes()); } } } diff --git a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Microsoft.EntityFrameworkCore.Commands.FunctionalTests.csproj b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Microsoft.EntityFrameworkCore.Commands.FunctionalTests.csproj index 93b61cfd0ce..30c9c6f74b9 100644 --- a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Microsoft.EntityFrameworkCore.Commands.FunctionalTests.csproj +++ b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/Microsoft.EntityFrameworkCore.Commands.FunctionalTests.csproj @@ -73,7 +73,7 @@ - + diff --git a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationExecutorWrapper.cs b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/AppDomainOperationExecutor.cs similarity index 92% rename from test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationExecutorWrapper.cs rename to test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/AppDomainOperationExecutor.cs index ff2d4b10ecc..ec1e1c55591 100644 --- a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationExecutorWrapper.cs +++ b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/AppDomainOperationExecutor.cs @@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Commands.TestUtilities { // NOTE: If you break this file, you probably broke the PowerShell module too. - public class OperationExecutorWrapper : IDisposable + public class AppDomainOperationExecutor : IDisposable { private const string AssemblyName = "Microsoft.EntityFrameworkCore.Commands"; private const string TypeName = "Microsoft.EntityFrameworkCore.Design.OperationExecutor"; @@ -19,7 +19,7 @@ public class OperationExecutorWrapper : IDisposable private readonly AppDomain _domain; private readonly object _executor; - public OperationExecutorWrapper( + public AppDomainOperationExecutor( string targetDir, string targetName, string projectDir, @@ -61,8 +61,8 @@ public OperationExecutorWrapper( public string GetContextType(string name) => InvokeOperation("GetContextType", new Hashtable { { "name", name } }); - public IEnumerable AddMigration(string name, string outputDir, string contextType) - => InvokeOperation>( + public IDictionary AddMigration(string name, string outputDir, string contextType) + => InvokeOperation( "AddMigration", new Hashtable { { "name", name }, { "outputDir", outputDir }, { "contextType", contextType } }); @@ -118,10 +118,10 @@ private object InvokeOperationImpl(string operation, Hashtable arguments, bool i if (resultHandler.ErrorType != null) { - throw new WrappedOperationException( - resultHandler.ErrorMessage, + throw new OperationErrorException( + resultHandler.ErrorType, resultHandler.ErrorStackTrace, - resultHandler.ErrorType); + resultHandler.ErrorMessage); } if (!isVoid && !resultHandler.HasResult) diff --git a/src/dotnet-ef/OperationException.cs b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationErrorException.cs similarity index 58% rename from src/dotnet-ef/OperationException.cs rename to test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationErrorException.cs index a345429b89e..1acfc51f697 100644 --- a/src/dotnet-ef/OperationException.cs +++ b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/OperationErrorException.cs @@ -1,16 +1,15 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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; -using JetBrains.Annotations; -namespace Microsoft.EntityFrameworkCore.Commands +namespace Microsoft.EntityFrameworkCore.Commands.TestUtilities { - public class OperationException : Exception + public class OperationErrorException : Exception { private readonly string _stackTrace; - public OperationException([NotNull] string type, [NotNull] string stackTrace, [NotNull] string message) + public OperationErrorException(string type, string stackTrace, string message) : base(message) { _stackTrace = stackTrace; diff --git a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/WrappedOperationException.cs b/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/WrappedOperationException.cs deleted file mode 100644 index bb22d5a06be..00000000000 --- a/test/Microsoft.EntityFrameworkCore.Commands.FunctionalTests/TestUtilities/WrappedOperationException.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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; - -namespace Microsoft.EntityFrameworkCore.Commands.TestUtilities -{ - public class WrappedOperationException : Exception - { - public WrappedOperationException(string message, string errorStackTrace, string errorType) - : base(message) - { - ErrorStackTrace = errorStackTrace; - ErrorType = errorType; - } - - public string ErrorStackTrace { get; } - - public string ErrorType { get; } - } -}