Azure Function 启动中的 EF Core 迁移

gre*_*ven 9 migration entity-framework .net-core azure-functions azure-function-app

根据https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection,在启动完成运行之后才应使用服务提供程序。事实上,如果我尝试获取注册服务,它将失败。

例子:

[assembly: FunctionsStartup(typeof(Startup))]

namespace Fx {
    public sealed class Startup : FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder) {
            var configurationBuilder = new ConfigurationBuilder();
            configurationBuilder.AddEnvironmentVariables();

            var configuration = configurationBuilder.Build();

            builder.Services.AddInfrastructure(configuration);
            builder.Services.AddApplication();

            var serviceProvider = builder.Services.BuildServiceProvider();
            DependencyInjection.AddDatabase(serviceProvider).GetAwaiter().GetResult();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
    public static class DependencyInjection {
        public static async Task AddDatabase(IServiceProvider services) {
            using var scope = services.CreateScope();

            var serviceProvider = scope.ServiceProvider;

            var context = serviceProvider.GetRequiredService<ApplicationDbContext>();
            //Error generated here
            if (context.Database.IsSqlServer()) {
                await context.Database.MigrateAsync();
            }
            await ApplicationDbContextSeed.SeedSamplePersonnelDataAsync(context);
        }

        public static IServiceCollection AddInfrastructure(
            this IServiceCollection services,
            IConfiguration configuration) {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                    b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));

            services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

            return services;
        }
    }
Run Code Online (Sandbox Code Playgroud)

这会产生以下错误

Microsoft.EntityFrameworkCore: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
Run Code Online (Sandbox Code Playgroud)

在启动期间是否有迁移和播种的好选择?

小智 10

我发现启动后运行代码的最简单方法是IWebJobsStartup使用WebJobsStartupAttributeFunctionsStartupAttribute实际上也继承自此属性)注册自定义。在 WebJobsStartup 类中,您需要使用AddExtension能够使用依赖项注入并为数据库提供种子的位置来注册扩展。我的代码:

[assembly: WebJobsStartup(typeof(DbInitializationService), "DbSeeder")]

namespace Our.Database.Seeder
{
    public class DbInitializationService : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            builder.AddExtension<DbSeedConfigProvider>();
        }
    }

    [Extension("DbSeed")]
    internal class DbSeedConfigProvider : IExtensionConfigProvider
    {
        private readonly IServiceScopeFactory _scopeFactory;

        public DbSeedConfigProvider(IServiceScopeFactory scopeFactory)
        {
            _scopeFactory = scopeFactory;
        }

        public void Initialize(ExtensionConfigContext context)
        {
            using var scope = _scopeFactory.CreateScope();
            var dbContext = scope.ServiceProvider.GetService<YourDbContext>();

            dbContext.Database.EnsureCreated();
            // Further DB seeding, etc.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Eim*_*eis 4

根据您的代码,我假设您正在构建与 Github 上的 CleanArchitecture 存储库一致的东西。https://github.com/jasontaylordev/CleanArchitecture

此存储库与您的应用程序之间的主要区别在于,您显然没有使用 ASP.NET,这根本不是问题,但需要更多的配置工作。

已经提到的文章(https://markheath.net/post/ef-core-di-azure-functions)引用了另一篇博文(https://dev.to/azure/using-entity-framework-with-azure-functions ) -50aa),它简要说明了 EntityFramework 迁移无法自动发现 Azure Function 中的迁移。因此,您需要实现一个IDesignTimeDbContextFactory. 我还在微软文档中偶然发现了它: https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation ?tabs=dotnet-core-cli#from-a-design-time-工厂

例如,您可以将其放入Infrastructure\Persistence\Configurations文件夹中。(再一次,我只是假设您遵循 CleanArchitecture 存储库结构)