首页 > 解决方案 > FluentMigrator 与 EF Core 和 Azure 托管标识

问题描述

在我当前的项目(.NET 5、ASP.NET Core)中,我们使用 FluentMigrator 运行 EF Core 迁移,它可以完美运行。我们正在 Azure 中设置我们的基础架构以通过托管身份进行通信,并设置了一个系统分配的托管身份,从我们的(Web)应用程序服务到我们的 SQL 服务器。

我们遵循本指南:https ://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi?tabs=windowsclient%2Cdotnetcore

但是,我们从 FluentMigrator 获得以下空指针引用:

FluentMigrator.Runner.Processors.SqlServer.SqlServer2016Processor[0]
There was an exception checking if table VersionInfo in (null) exists
System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
---> System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider.<AcquireTokenInteractiveDeviceFlowAsync>b__18_0(DeviceCodeResult deviceCodeResult)
 at Microsoft.Identity.Client.Internal.Requests.DeviceCodeRequest.ExecuteAsync(CancellationToken cancellationToken)
 at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
 at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireToken CommonParameters commonParameters, AcquireTokenWithDeviceCodeParameters deviceCodeParameters, CancellationToken cancellationToken)
at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider.AcquireTokenInteractiveDeviceFlowAsync(IPublicClientApplication app, String[] scopes, Guid connectionId, String userId, SqlAuthenticationMethod authenticationMethod, CancellationTokenSource cts)
at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider.AcquireTokenAsync(SqlAuthenticationParameters parameters)
--- End of inner exception stack trace ---
at Microsoft.Data.ProviderBase.DbConnectionPool.CheckPoolBlockingPeriod(Exception e)
at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open()
at FluentMigrator.Runner.Processors.GenericProcessorBase.<>c__DisplayClass6_1.<.ctor>b__1()

我想这是因为 FluentMigrator 无法使用连接字符串连接到数据库:

"Server=tcp:<server-name>.database.windows.net;Authentication=Active Directory Device Code Flow; Database=<database-name>;"

但我可能错了:-)

StartUp.cs我们这样注册 FluentMigrator 中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddFluentMigratorCore()
            .ConfigureRunner(rb => rb
                .AddSqlServer()
                .WithGlobalConnectionString(databaseConnectionString)
                .ScanIn(typeof(Startup).Assembly).For.Migrations());
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    using IServiceScope scope = app.ApplicationServices.CreateScope();
        IMigrationRunner runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();

        runner.MigrateUp();
}

有谁知道是否有可能让 FluentMigrator 在 Azure 中使用 AD/托管身份?

非常感谢任何帮助/提示。

提前致谢。

编辑:如果我们注释掉 FluentMigrator 注册,我们的应用服务运行良好。

标签: c#azureentity-framework-corefluent-migrator

解决方案


FluentMigrator 完全没有问题。只是我有一个狭隘的视野,并遵循微软的指南,他们把SqlAuthenticationProvider.SetProvider(...)里面放在了services.AddDbContext<T>(...):-) 把它移到外面,AddDbContext<T>(..)就像这样使它工作:

SqlAuthenticationProvider.SetProvider(
            SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow,
            new ManagedIdentitySqlAuthProvider());

services.AddDbContext<BasketApiDbContext>(options =>
{
    options.UseSqlServer(databaseConnectionString);
});

推荐阅读