diff --git a/src/EFCore.Design/Design/Internal/AppServiceProviderFactory.cs b/src/EFCore.Design/Design/Internal/AppServiceProviderFactory.cs
index b797f8a4add..456184ec46a 100644
--- a/src/EFCore.Design/Design/Internal/AppServiceProviderFactory.cs
+++ b/src/EFCore.Design/Design/Internal/AppServiceProviderFactory.cs
@@ -89,4 +89,30 @@ private IServiceProvider CreateEmptyServiceProvider()
return new ServiceCollection().BuildServiceProvider();
}
+
+ ///
+ /// 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.
+ ///
+ public static void SetEnvironment(IOperationReporter reporter)
+ {
+ var aspnetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
+ var dotnetEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
+ var environment = aspnetCoreEnvironment
+ ?? dotnetEnvironment
+ ?? "Development";
+ if (aspnetCoreEnvironment == null)
+ {
+ Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", environment);
+ }
+
+ if (dotnetEnvironment == null)
+ {
+ Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", environment);
+ }
+
+ reporter.WriteVerbose(DesignStrings.UsingEnvironment(environment));
+ }
}
diff --git a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs
index d27a2532b3c..f02f26bf4ed 100644
--- a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs
+++ b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs
@@ -11,6 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Design.Internal;
///
public class DatabaseOperations
{
+ private readonly IOperationReporter _reporter;
private readonly string _projectDir;
private readonly string? _rootNamespace;
private readonly string? _language;
@@ -34,6 +35,7 @@ public DatabaseOperations(
bool nullable,
string[]? args)
{
+ _reporter = reporter;
_projectDir = projectDir;
_rootNamespace = rootNamespace;
_language = language;
@@ -73,6 +75,7 @@ public virtual SavedModelFiles ScaffoldContext(
? Path.GetFullPath(Path.Combine(_projectDir, outputContextDir))
: outputDir;
+ AppServiceProviderFactory.SetEnvironment(_reporter);
var services = _servicesBuilder.Build(provider);
using var scope = services.CreateScope();
diff --git a/src/EFCore.Design/Design/Internal/DbContextOperations.cs b/src/EFCore.Design/Design/Internal/DbContextOperations.cs
index 761579c8bdb..f430f9892b0 100644
--- a/src/EFCore.Design/Design/Internal/DbContextOperations.cs
+++ b/src/EFCore.Design/Design/Internal/DbContextOperations.cs
@@ -503,22 +503,7 @@ private IDictionary> FindContextTypes(string? name = null,
{
_reporter.WriteVerbose(DesignStrings.FindingContexts);
- var aspnetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
- var dotnetEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
- var environment = aspnetCoreEnvironment
- ?? dotnetEnvironment
- ?? "Development";
- if (aspnetCoreEnvironment == null)
- {
- Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", environment);
- }
-
- if (dotnetEnvironment == null)
- {
- Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", environment);
- }
-
- _reporter.WriteVerbose(DesignStrings.UsingEnvironment(environment));
+ AppServiceProviderFactory.SetEnvironment(_reporter);
var contexts = new Dictionary?>();
diff --git a/test/EFCore.Design.Tests/Design/Internal/DatabaseOperationsTest.cs b/test/EFCore.Design.Tests/Design/Internal/DatabaseOperationsTest.cs
index d5c7a100554..d49bac41616 100644
--- a/test/EFCore.Design.Tests/Design/Internal/DatabaseOperationsTest.cs
+++ b/test/EFCore.Design.Tests/Design/Internal/DatabaseOperationsTest.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Microsoft.EntityFrameworkCore.Internal;
+
namespace Microsoft.EntityFrameworkCore.Design.Internal;
public class DatabaseOperationsTest
@@ -10,8 +12,71 @@ public void Can_pass_null_args()
{
// Even though newer versions of the tools will pass an empty array
// older versions of the tools can pass null args.
+ CreateOperations(null);
+ }
+
+ [ConditionalFact]
+ public void ScaffoldContext_throws_exceptions_for_invalid_context_name()
+ {
+ ValidateContextNameInReverseEngineerGenerator("Invalid!CSharp*Class&Name");
+ ValidateContextNameInReverseEngineerGenerator("1CSharpClassNameCannotStartWithNumber");
+ ValidateContextNameInReverseEngineerGenerator("volatile");
+ }
+
+ private void ValidateContextNameInReverseEngineerGenerator(string contextName)
+ {
+ var operations = CreateOperations([]);
+
+ Assert.Equal(
+ DesignStrings.ContextClassNotValidCSharpIdentifier(contextName),
+ Assert.Throws(
+ () => operations.ScaffoldContext(
+ "Microsoft.EntityFrameworkCore.SqlServer",
+ "connectionstring",
+ "",
+ "",
+ dbContextClassName: contextName,
+ null,
+ null,
+ "FakeNamespace",
+ contextNamespace: null,
+ useDataAnnotations: false,
+ overwriteFiles: true,
+ useDatabaseNames: false,
+ suppressOnConfiguring: true,
+ noPluralize: false))
+ .Message);
+ }
+
+ [ConditionalFact]
+ [SqlServerConfiguredCondition]
+ public void ScaffoldContext_sets_environment()
+ {
+ var operations = CreateOperations([]);
+ operations.ScaffoldContext(
+ "Microsoft.EntityFrameworkCore.SqlServer",
+ TestEnvironment.DefaultConnection,
+ "",
+ "",
+ dbContextClassName: nameof(TestContext),
+ schemas: ["Empty"],
+ null,
+ null,
+ contextNamespace: null,
+ useDataAnnotations: false,
+ overwriteFiles: true,
+ useDatabaseNames: false,
+ suppressOnConfiguring: true,
+ noPluralize: false);
+
+ Assert.Equal("Development", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
+ Assert.Equal("Development", Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"));
+ }
+
+ private static DatabaseOperations CreateOperations(string[] args)
+ {
var assembly = MockAssembly.Create(typeof(TestContext));
- _ = new TestDatabaseOperations(
+ var operations = new DatabaseOperations(
new TestOperationReporter(),
assembly,
assembly,
@@ -19,7 +84,8 @@ public void Can_pass_null_args()
"RootNamespace",
"C#",
nullable: false,
- args: null);
+ args: args);
+ return operations;
}
public class TestContext : DbContext;
diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
index ba445da389c..15f7e341fcf 100644
--- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
+++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
@@ -2453,7 +2453,7 @@ public void InsertDataOperation_required_empty_array()
Assert.Single(o.Columns);
Assert.Equal(1, o.Values.GetLength(0));
Assert.Equal(1, o.Values.GetLength(1));
- Assert.Equal([], (string[])o.Values[0, 0]);
+ Assert.Equal(new string[0], (string[])o.Values[0, 0]);
});
[ConditionalFact]
@@ -2478,7 +2478,7 @@ public void InsertDataOperation_required_empty_array_composite()
Assert.Equal(1, o.Values.GetLength(0));
Assert.Equal(3, o.Values.GetLength(1));
Assert.Null(o.Values[0, 1]);
- Assert.Equal([], (string[])o.Values[0, 2]);
+ Assert.Equal(new string[0], (string[])o.Values[0, 2]);
});
[ConditionalFact]
diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineeringConfigurationTests.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineeringConfigurationTests.cs
deleted file mode 100644
index e73a91f883a..00000000000
--- a/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineeringConfigurationTests.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.EntityFrameworkCore.Design.Internal;
-using Microsoft.EntityFrameworkCore.Internal;
-
-namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal;
-
-public class ReverseEngineeringConfigurationTests
-{
- [ConditionalFact]
- public void Throws_exceptions_for_invalid_context_name()
- {
- ValidateContextNameInReverseEngineerGenerator("Invalid!CSharp*Class&Name");
- ValidateContextNameInReverseEngineerGenerator("1CSharpClassNameCannotStartWithNumber");
- ValidateContextNameInReverseEngineerGenerator("volatile");
- }
-
- private void ValidateContextNameInReverseEngineerGenerator(string contextName)
- {
- var assembly = typeof(ReverseEngineeringConfigurationTests).Assembly;
- var reverseEngineer = new DesignTimeServicesBuilder(assembly, assembly, new TestOperationReporter(), [])
- .Build("Microsoft.EntityFrameworkCore.SqlServer")
- .CreateScope()
- .ServiceProvider
- .GetRequiredService();
-
- Assert.Equal(
- DesignStrings.ContextClassNotValidCSharpIdentifier(contextName),
- Assert.Throws(
- () => reverseEngineer.ScaffoldModel(
- "connectionstring",
- new DatabaseModelFactoryOptions(),
- new ModelReverseEngineerOptions(),
- new ModelCodeGenerationOptions { ModelNamespace = "FakeNamespace", ContextName = contextName }))
- .Message);
- }
-}
diff --git a/test/EFCore.Design.Tests/TestUtilities/TestDatabaseOperations.cs b/test/EFCore.Design.Tests/TestUtilities/TestDatabaseOperations.cs
deleted file mode 100644
index adf200ef857..00000000000
--- a/test/EFCore.Design.Tests/TestUtilities/TestDatabaseOperations.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.EntityFrameworkCore.Design.Internal;
-
-namespace Microsoft.EntityFrameworkCore.TestUtilities;
-
-public class TestDatabaseOperations(
- IOperationReporter reporter,
- Assembly assembly,
- Assembly startupAssembly,
- string projectDir,
- string rootNamespace,
- string language,
- bool nullable,
- string[] args) : DatabaseOperations(reporter, assembly, startupAssembly, projectDir, rootNamespace, language, nullable, args);
diff --git a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs
index 75dd606cd19..b118885ba85 100644
--- a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs
+++ b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs
@@ -677,7 +677,7 @@ public void Navigations_on_base_type_should_be_inherited()
var specialCustomerType = model.AddEntityType(typeof(SpecialCustomer));
Assert.Equal(new[] { "Orders" }, customerType.GetNavigations().Select(p => p.Name).ToArray());
- Assert.Equal([], specialCustomerType.GetNavigations().Select(p => p.Name).ToArray());
+ Assert.Equal(new string[0], specialCustomerType.GetNavigations().Select(p => p.Name).ToArray());
specialCustomerType.BaseType = customerType;
diff --git a/test/EFCore.Tests/Storage/ValueConversion/BytesToStringConverterTest.cs b/test/EFCore.Tests/Storage/ValueConversion/BytesToStringConverterTest.cs
index a29063dc5ab..c1a2694ba2f 100644
--- a/test/EFCore.Tests/Storage/ValueConversion/BytesToStringConverterTest.cs
+++ b/test/EFCore.Tests/Storage/ValueConversion/BytesToStringConverterTest.cs
@@ -23,7 +23,7 @@ public void Can_convert_bytes_to_strings()
var converter = _bytesToStringConverter.ConvertFromProviderExpression.Compile();
Assert.Equal(new byte[] { 83, 112, 196, 177, 110, 204, 136, 97, 108, 32, 84, 97, 112 }, converter("U3DEsW7MiGFsIFRhcA=="));
- Assert.Equal([], converter(""));
+ Assert.Equal(new byte[0], converter(""));
}
[ConditionalFact]
diff --git a/test/EFCore.Tests/Storage/ValueConversion/StringToBytesConverterTest.cs b/test/EFCore.Tests/Storage/ValueConversion/StringToBytesConverterTest.cs
index f2aa07d914c..6842b227c4a 100644
--- a/test/EFCore.Tests/Storage/ValueConversion/StringToBytesConverterTest.cs
+++ b/test/EFCore.Tests/Storage/ValueConversion/StringToBytesConverterTest.cs
@@ -13,7 +13,7 @@ public void Can_convert_strings_to_UTF8()
var converter = _stringToUtf8Converter.ConvertToProviderExpression.Compile();
Assert.Equal(new byte[] { 83, 112, 196, 177, 110, 204, 136, 97, 108, 32, 84, 97, 112 }, converter("Spın̈al Tap"));
- Assert.Equal([], converter(""));
+ Assert.Equal(new byte[0], converter(""));
}
[ConditionalFact]