You*_*qra 3 c# dependency-injection dbcontext entity-framework-core .net-core
我创建了一个 .net Core 控制台应用程序,并添加了以下依赖项注入包:
Microsoft.Extensions.DependencyInjection
要注入 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;
}
Run Code Online (Sandbox Code Playgroud)
服务池类别:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
MigrationDbContext 服务从 EntityFramwork Core 实现 DbContext:
public class MigrationDbContext : DbContext
{
public MigrationDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}
public DbSet<RootItemMigrationEntity> RootItems { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
该应用程序运行没有任何问题,但是当我尝试使用以下命令创建初始迁移时:
添加迁移“初始”
出现错误并显示以下消息:
无法创建“MigrationDbContext”类型的对象。有关设计时支持的不同模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728
我一直在调查这个问题,并尝试了多种解决方案,但仍无法解决。因此,我将分享错误的堆栈跟踪,希望能得到您的帮助!
堆栈跟踪:
PM> Add-Migration 'Initial' -verbos 使用项目 'migration.presentence'。使用启动项目“e-commerce.migration”。构建开始...构建成功。C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\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.json C:\Users\yousi.nuget\packages\microsoft.entityframeworkcore.tools\5.0.1\tools\netcoreapp2.0\any\ef.dll 迁移添加初始 --json --verbose --no-color - -前缀输出--程序集C:\ dev \ backlogheros \ e-commerce.migration \ e-commerce.migration \ bin \ Debug \ netcoreapp5.0 \ migration.presentence.dll --启动程序集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 使用程序集“migration.presentence”。使用启动程序集“e-commerce.migration”。使用应用程序库“C:\dev\backlogheros\e-commerce.migration\e-commerce.migration\bin\Debug\netcoreapp5.0”。使用工作目录“C:\dev\backlogheros\e-commerce.migration\e-commerce.migration”。使用根命名空间“migration.presentence”。使用项目目录“C:\dev\backlogheros\e-commerce.migration\migration.presentence”。剩余参数: . 查找 DbContext 类...查找 IDesignTimeDbContextFactory 实现...在程序集“e-commerce.migration”中查找应用程序服务提供程序...查找 Microsoft.Extensions.Hosting 服务提供程序...没有静态方法“CreateHostBuilder(string[])”在“程序”类中找到。未找到应用服务提供商。正在项目中查找 DbContext 类...找到 DbContext 'MigrationDbContext'。Microsoft.EntityFrameworkCore.Design.OperationException:无法创建“MigrationDbContext”类型的对象。有关设计时支持的不同模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728 ---> System.InvalidOperationException: 尝试时无法解析类型“Microsoft.EntityFrameworkCore.DbContextOptions”的服务激活“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)
Run Code Online (Sandbox Code Playgroud)
迁移工具必须实例化您的 DbContext 才能创建迁移。它有 3 种方法可以做到这一点:
如果您希望迁移工具使用应用程序配置并解析来自服务提供商的 DbContext,则需要满足多个要求,如页面https://go.microsoft.com/fwlink/?linkid=851728中所述。
首先,您需要有一个DbContextOptions在 DbContext 上接受 a 的构造函数。DbContextOptions<TContext>该部分没问题,仅当程序集中有多个 DbContext 时才需要指定。
public static CreateHostBuilder(string[] args)其次,您必须使用主机构建器(ASP.NET、HTTP 或 Generic),该工具将在类中查找方法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();
}
}
Run Code Online (Sandbox Code Playgroud)
为了使您的主机构建器运行您的自定义代码,您还需要将该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();
}
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是在 DbContext 上使用默认构造。但是,在这种情况下,您不能DbContextOptions同时拥有默认构造函数和构造函数。伤心。
根据您的情况,最简单的解决方案可能是实施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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8492 次 |
| 最近记录: |