使用简单注入器更新数据库,没有 services.AddDbContext<>()

Update-Database using Simple Injector, without services.AddDbContext<>()

.NET Core 3.1、EF Core 5.0 预览版 6.

我正在使用 Simple Injector 5.0 注册 IMyContextFactory(我没有使用 services.AddDbContext<>())。

我的 MyContext 将所有构造函数设置为私有,因为我使用不带 tenantId 的 ContextFactory,有时在一个请求中使用几个不同的 tenantId,所以我确保每个人都会使用 IMyContextFactory 注入而不是 MyContext 并防止在控制器等中创建 new MyContext()

但是怎么办Update-Database?

  1. 虽然我这样做 Update-Database 我总是有错误 Login failed for user ''.,但我可以 运行 并从我的 WebAPI 项目连接到数据库没有任何问题(我的 ConnectionString 很好)。
  2. 我能够在 运行 时应用迁移,但我必须添加 services.AddDbContext<MyContext>(),将 MyContext 的构造函数设为 public 并从 scope.ServiceProvider.GetRequiredService<MyContext>() 在 Program.cs,因为我的 IMyContextFactory 不在 ServiceProvider 里面。 (来自 https://docs.microsoft.com/pl-pl/ef/core/managing-schemas/migrations/applying?tabs=vs#apply-migrations-at-runtime

如何仅使用 Simple Injector 实现?

解决方法是安装 Entity Framework Core .NET Command-line Tools 并从中更新数据库。

注意:在 Visual Studio 中禁用所有私有 NuGet 存储库并在程序包管理器控制台中安装工具:

dotnet tool install --global dotnet-ef --version 5.0.0-preview.6.20312.4

现在您可以在 Visual Studio 中启用您的私有 NuGet 源。

然后,转到您的上下文和配置所在的文件夹,然后:

dotnet ef database update --connection "Your=Connection;String"

您还可以使用 Update-Database:

更改连接字符串
Update-Database -connection "Your=Connection;String"

但这是解决方法。我仍在向您寻求“内部”解决方案 Visual Studio IDE,无需安装额外的 CMD 工具

解决方案是将 ConnectionString 添加到您的 IDesignTimeDbContextFactory 实现中:

// Fix for "Unable to create an object of type 'MyContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728" error while creating migration
public class MyContextDesignFactory : IDesignTimeDbContextFactory<MyContext>
{
    private string _appsettingsPath = "./../Path/To/ProjectWithAppsettingsJSON";

    public MyContext CreateDbContext(string[] args)
    {
        // In 90% we don't have ASPNETCORE_ENVIRONMENT here, so set fallback to Development
        var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development";

        var config = new ConfigurationBuilder()
            .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), _appsettingsPath))
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{environment}.json", optional: true)
            .Build();

        Console.WriteLine($"Default ConnectionString comes from appsettings file.{Environment.NewLine}You can override it by using `dotnet ef database update --connection MyConnectionString`");

        // Use ConnectionString from appsettings inside WebAPI to fix `Update-Database` command from Package Manager Console
        // We still can override ConnectionString by `dotnet ef database update --connection MyConnectionString`
        var optionsBuilder = new DbContextOptionsBuilder<MyContext>()
            .UseSqlServer(config["ConnectionString"]);

        return MyContext.MyContextFactory.GetMyContext(optionsBuilder.Options);
    }
}