dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.6k stars 10.06k forks source link

Improve Error Message and/or Docs around InvariantGlobalization true by default #53678

Open ardalis opened 10 months ago

ardalis commented 10 months ago

I'd like to share some experience here. I just created a new webapi project and then added EF Core support. I didn't pay super close attention to the template's csproj file, as I assumed it would basically work as it has in the past. If I noticed the existence of this property it didn't jump out at me:

<InvariantGlobalization>true</InvariantGlobalization>

So, it came as a surprise to me when I had finished adding EF Core DbContext support and was using the CLI to create migrations, as I've done 100s of times in the past, and when I tried to update my localdb SQL Server I got this:

System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
en-us is an invalid culture identifier.
   at System.Globalization.CultureInfo.GetCultureInfo(String name)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.<Execute>b__0(DbContext _, TState s)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists(Boolean retryOnNotExists)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
en-us is an invalid culture identifier.

Now, knowing I'd just created this project I was 100% sure I hadn't specified "en-us" anywhere in my code to configure and set up my DbContext. There's nothing in this that suggests I should look at my Web API project. The stack trace only includes EF Core types. Fortunately, my search led me to the setting and issues like this one:

https://github.com/dotnet/SqlClient/issues/2239

(and probably this issue's existence will help others as well)

Proposal

Improve the error message shown above to suggest checking the application's project file to see if <InvariantCulture> has been set and, if so, to remove that setting (or set it to false).

Alternately, figure out a way to make local SQLServer development work with invariant culture.

captainsafia commented 7 months ago

I just created a new webapi project

I believe we only set InvariantGlobalization=true when you use the AoT-enabled Web API template. Can you verify if this is the case?

Assuming so, @eerhardt do we document the fact that this is set for AoT templates anywhere?

eerhardt commented 7 months ago

I believe we only set InvariantGlobalization=true when you use the AoT-enabled Web API template. Can you verify if this is the case?

There was a time (8.0.0 - 8.0.1) where we were setting it in the webapi template regardless if you used AOT or not. This was fixed in 8.0.2 with https://github.com/dotnet/aspnetcore/pull/52461. If you are using the latest patches, this is now fixed.

do we document the fact that this is set for AoT templates anywhere?

I'm not sure and I don't know where that would be documented (maybe it should be on https://learn.microsoft.com/aspnet/core/fundamentals/native-aot?). This is basically a performance optimization. Since you are using AOT, we figured it makes sense to default to this mode. See https://github.com/dotnet/aspnetcore/issues/47029.

ardalis commented 7 months ago

I wasn't using an AOT template (must've been 8.0.0-8.0.1). Sounds like this can probably be closed if it's resolved in the template (though I'd make sure the docs for AOT templates are clear about this).