gpt4 book ai didi

c# - 在 .NET Core 控制台应用程序中针对 EF Core DbContext 服务错误建立依赖注入(inject)

转载 作者:行者123 更新时间:2023-12-02 02:26:36 26 4
gpt4 key购买 nike

我创建了一个 .net Core 控制台应用程序,并添加了以下依赖注入(inject)包:

Microsoft.Extensions.DependencyInjection

要注入(inject) EF Core DbContext 服务,这里是项目的代码片段:

static void Main(string[] args)
{
// Create service collection and configure our services
var services = ConfigureServices();

// Generate a provider
var serviceProvider = services.BuildServiceProvider();

// Kick off our actual code
serviceProvider.GetService<Startup>().Run();
}

public static IConfiguration LoadConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables();

return builder.Build();
}


private static IServiceCollection ConfigureServices()
{
IServiceCollection services = new ServiceCollection();

// Set up the objects we need to get to configuration settings
var configuration = LoadConfiguration();


// IMPORTANT! Register our cvonfig file, db connection string, and application entry point(startup)
services
.AddSingleton(configuration)
.AddConnection(configuration)
.AddStartup();

return services;
}

服务池类:

  public static class ServicesPool
{
public static IServiceCollection AddStartup(this IServiceCollection services)
{
services.AddTransient<Startup>();

return services;
}

public static IServiceCollection AddConfiggguration(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton(configuration);

return services;
}

public static IServiceCollection AddConnection(this IServiceCollection services, IConfiguration configuration)
{
var connection = configuration.GetConnectionString("DEV_CS");
services.AddDbContext<MigrationDbContext>(options =>
options.UseSqlServer(connection, b => b.MigrationsAssembly("migration.presentence")));

return services;
}

}

从 EntityFramwork Core 实现 DbContext 的 MigrationDbContext 服务:

public class MigrationDbContext : DbContext
{
public MigrationDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}

public DbSet<RootItemMigrationEntity> RootItems { get; set; }

}

应用程序运行没有任何问题,但是当我尝试使用以下命令创建初始迁移时:

Add-Migration 'Initial'

以下消息出错:

Unable to create an object of type 'MigrationDbContext'. For thedifferent patterns supported at design time, seehttps://go.microsoft.com/fwlink/?linkid=851728

我一直在调查这个问题,我已经尝试了多种解决方案,但我仍然无法解决它。所以我将分享错误的堆栈跟踪,希望得到您的帮助!

堆栈跟踪:

PM> Add-Migration 'Initial' -verbos Using project'migration.presentence'. Using startup project 'e-commerce.migration'.Build started... Build succeeded. C:\Program Files\dotnet\dotnet.exeexec --depsfileC:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0\e-commerce.migration.deps.json--additionalprobingpath C:\Users\yousi.nuget\packages --runtimeconfig C:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0\e-commerce.migration.runtimeconfig.jsonC:\Users\yousi.nuget\packages\microsoft.entityframeworkcore.tools\5.0.1\tools\netcoreapp2.0\any\ef.dllmigrations add Initial --json --verbose --no-color --prefix-output--assembly C:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0\migration.presentence.dll--startup-assembly C:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0\e-commerce.migration.dll--project-dir C:\dev\backlogheros\e-commerce.migration\migration.presentence
--language C# --working-dir C:\dev\backlogheros\e-commerce.migration --root-namespace migration.presentence Using assembly 'migration.presentence'. Using startup assembly'e-commerce.migration'. Using application base'C:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0'.Using working directory'C:\dev\backlogheros\e-commerce.migration\e-commerce.migration'. Usingroot namespace 'migration.presentence'. Using project directory'C:\dev\backlogheros\e-commerce.migration\migration.presentence'.Remaining arguments: . Finding DbContext classes... FindingIDesignTimeDbContextFactory implementations... Finding applicationservice provider in assembly 'e-commerce.migration'... FindingMicrosoft.Extensions.Hosting service provider... No static method'CreateHostBuilder(string[])' was found on class 'Program'. Noapplication service provider was found. Finding DbContext classes inthe project... Found DbContext 'MigrationDbContext'.Microsoft.EntityFrameworkCore.Design.OperationException: Unable tocreate an object of type 'MigrationDbContext'. For the differentpatterns supported at design time, seehttps://go.microsoft.com/fwlink/?linkid=851728 --->System.InvalidOperationException: Unable to resolve service for type'Microsoft.EntityFrameworkCore.DbContextOptions' while attempting toactivate 'migration.presentence.MigrationDbContext'.

at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)   
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_4.<FindContextTypes>b__13()
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_4.<FindContextTypes>b__13()
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

最佳答案

迁移工具必须实例化您的 DbContext 才能创建迁移。它有 3 种方法可以做到这一点:

  1. 由服务提供商解决
  2. 新()
  3. IDesignTimeDbContextFactory

由服务提供商解决

如果您希望迁移工具使用应用程序配置并解析来自服务提供商的 DbContext,则有多个要求,如第 https://go.microsoft.com/fwlink/?linkid=851728 页所述.

首先,您需要有一个接受 DbContextOptions 的构造函数在你的 DbContext 上。那部分没问题,你需要指定DbContextOptions<TContext>仅当您的程序集中有多个 DbContext 时。

其次,您必须使用主机构建器(ASP.NET、HTTP 或通用),该工具将查找 public static CreateHostBuilder(string[] args)类中的方法 Program访问它。自 IHostBuilder 以来,这对您的基础设施类有很多副作用。将为您完成 ServiceCollection 的大部分工作, 和 ConfigurationBuilder东西。

此外,您的 DbContext 需要注册为单例,这可能是个问题。

程序.cs

internal class Program
{
public static void LoadConfiguration(HostBuilderContext host, IConfigurationBuilder builder)
{
builder
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables();
}

private static void ConfigureServices(HostBuilderContext host, IServiceCollection services)
{
services
.AddDbContext<MigrationDbContext>(options =>
{
options.UseSqlServer(
host.Configuration.GetConnectionString("DEV_CS"), builder =>
builder.MigrationsAssembly("migration.presentence"));
}, ServiceLifetime.Singleton)
.AddHostedService<Startup>();
}

private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(LoadConfiguration)
.ConfigureServices(ConfigureServices);

private static async Task Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
}

为了让您的主机构建器运行您的自定义代码,您还需要打开 Startup类变成 IHostedService例如BackgroundService例如。

启动.cs

internal class Startup : BackgroundService
{
private readonly MigrationDbContext context;

public Startup(MigrationDbContext context)
{
this.context = context ?? throw new ArgumentNullException(nameof(context));
}

protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
throw new NotImplementedException();
}
}

新()

另一种选择是在 DbContext 上使用默认构造。但是,在那种情况下,您不能同时拥有默认构造函数和 DbContextOptions构造函数同时。伤心。

IDesignTimeDbContextFactory

在您的情况下,最简单的解决方案可能是实现 IDesignTimeDbContextFactory<TContext> .如果找不到 IHostBuilder,工具将使用此类。并且 DbContext 使用 DbContextOptions构造函数。实现非常简单:

internal class MigrationDbContextFactory : IDesignTimeDbContextFactory<MigrationDbContext>
{
public MigrationDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<MigrationDbContext>();
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Test",
b => b.MigrationsAssembly("migration.presentence"));
return new MigrationDbContext(optionsBuilder.Options);
}
}

关于c# - 在 .NET Core 控制台应用程序中针对 EF Core DbContext 服务错误建立依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65564889/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com