EF Core DB First,以及如何避免模型生成时构造函数覆盖 [英] EF Core DB First, and how to avoid Constructor Overwrite on Model Generation

查看:58
本文介绍了EF Core DB First,以及如何避免模型生成时构造函数覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从对我的Azure DB使用SQL身份验证转移到Active Directory托管身份验证,如本

I am moving away from using SQL Authentication with my Azure DB, to Active Directory Managed Authentication as explained in this article.

基本上,我正在做两件事以使此工作正常进行.

Basically, I'm doing two main things to get this working.

1-在DBContext构造函数中注入令牌:

1- injecting the token in the DBContext constructor:

public MyDBContext(DbContextOptions<MyDBContext> options)
    : base(options)
{
    var conn = (SqlConnection)Database.GetDbConnection();
    conn.AccessToken = (new Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;

}

2-在我的Web App启动文件中,我正在注入DBContext

2- In My Web App Startup file, I'm injecting the DBContext

    string SqlConnection = localConfig["SqlConnectionString"];
    services.AddDbContext<MyDBContext>(options => options.UseSqlServer(SqlConnection, sqlServerOptions => { sqlServerOptions.CommandTimeout(1000); }));

我现在的问题是,每次需要使用 Scaffold-DbContext 命令刷新模型时,我的 MyDbContext 都会被覆盖,而我所做的更改也会丢失完成到构造函数.

My problem now is that every time I need to refresh the model using the Scaffold-DbContext command, my MyDbContext gets overwritten, and I lose the changes I've done to the constructor.

有什么解决方案可以避免此问题?或者,是否有更好的方式将令牌有效地有效地注入?

What solutions are possible to avoid this problem? OR, is there a better way to inject the Token somewhere else efficiently?

请注意,我正在使用EF 2.x

推荐答案

我已经使用拦截器注入访问令牌:

I've used an interceptor to inject access tokens:

public class ManagedIdentityConnectionInterceptor : DbConnectionInterceptor
{
    private readonly bool _useManagedIdentity;
    private readonly AzureServiceTokenProvider _tokenProvider;

    public ManagedIdentityConnectionInterceptor(bool useManagedIdentity)
    {
        _useManagedIdentity = useManagedIdentity;
        _tokenProvider = new AzureServiceTokenProvider();
    }

    public override async Task<InterceptionResult> ConnectionOpeningAsync(
        DbConnection connection,
        ConnectionEventData eventData,
        InterceptionResult result,
        CancellationToken cancellationToken = default)
    {
        if (_useManagedIdentity)
        {
            // In Azure, get an access token for the connection
            var sqlConnection = (SqlConnection)connection;
            var accessToken = await GetAccessTokenAsync(cancellationToken);
            sqlConnection.AccessToken = accessToken;
        }

        return result;
    }

    private async Task<string> GetAccessTokenAsync(CancellationToken cancellationToken)
    {
        // Get access token for Azure SQL DB
        var resource = "https://database.windows.net/";
        return await _tokenProvider.GetAccessTokenAsync(resource, cancellationToken: cancellationToken);
    }
}

可以这样添加:

// Detect environment somehow (locally you might not want to use tokens)
var useManagedIdentity = true;
var managedIdentityInterceptor = new ManagedIdentityConnectionInterceptor(useManagedIdentity);
services.AddDbContext<Context>(options => options.UseSqlServer(connectionString).AddInterceptors(managedIdentityInterceptor));

这样,无需在构造函数中进行任何更改.在打开与SQL DB的连接之前,拦截器将获得令牌.另外,我们避免在构造函数中进行异步同步.请注意,这需要EF Core 3.x.

This way no changes are needed in the constructor. The interceptor will get a token before a connection is opened to the SQL DB. Also we avoid doing sync-over-async in the constructor. Do note this requires EF Core 3.x.

这篇关于EF Core DB First,以及如何避免模型生成时构造函数覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆