Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF Core DB优先,以及如何避免在模型生成时重写构造函数_C#_Azure_Entity Framework_Entity Framework Core_Azure Active Directory - Fatal编程技术网

C# EF Core DB优先,以及如何避免在模型生成时重写构造函数

C# EF Core DB优先,以及如何避免在模型生成时重写构造函数,c#,azure,entity-framework,entity-framework-core,azure-active-directory,C#,Azure,Entity Framework,Entity Framework Core,Azure Active Directory,我将不再对Azure DB使用SQL身份验证,而是使用Active Directory管理的身份验证,如本文所述 基本上,我正在做两件主要的事情来让它工作 1-在DBContext构造函数中注入令牌: public MyDBContext(DbContextOptions<MyDBContext> options) : base(options) { var conn = (SqlConnection)Database.GetDbConnection(); c

我将不再对Azure DB使用SQL身份验证,而是使用Active Directory管理的身份验证,如本文所述

基本上,我正在做两件主要的事情来让它工作

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

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;

}
public MyDBContext(DbContextOptions)
:基本(选项)
{
var conn=(SqlConnection)数据库.GetDbConnection();
conn.AccessToken=(新的Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync(“https://database.windows.net/三、结果;
}
2-在我的Web应用程序启动文件中,我正在注入DBContext

    string SqlConnection = localConfig["SqlConnectionString"];
    services.AddDbContext<MyDBContext>(options => options.UseSqlServer(SqlConnection, sqlServerOptions => { sqlServerOptions.CommandTimeout(1000); }));
string SqlConnection=localConfig[“SqlConnectionString”];
services.AddDbContext(options=>options.UseSqlServer(SqlConnection,sqlServerOptions=>{sqlServerOptions.CommandTimeout(1000);}));
现在我的问题是,每次我需要使用
Scaffold DbContext
命令刷新模型时,我的
MyDbContext
都会被覆盖,并且我会丢失对构造函数所做的更改

有什么办法可以避免这个问题?或者,是否有更好的方法将令牌有效地注入到其他地方

编辑:
请注意,我使用的是EF 2.x

我使用了一个拦截器来注入访问令牌:

公共类ManagedEntityConnectionInterceptor:DbConnectionInterceptor
{
私有只读bool_useManagedEntity;
专用只读AzureServiceTokenProvider\u tokenProvider;
公共ManagedIdentityConnectionInterceptor(bool-useManagedIdentity)
{
_useManagedIdentity=useManagedIdentity;
_tokenProvider=新AzureServiceTokenProvider();
}
公共覆盖异步任务连接打开同步(
数据库连接,
ConnectionEventData事件数据,
拦截结果,
CancellationToken CancellationToken=默认值)
{
如果(_useManagedIndentity)
{
//在Azure中,获取连接的访问令牌
var sqlConnection=(sqlConnection)connection;
var accessToken=await GetAccessTokenAsync(cancellationToken);
sqlConnection.AccessToken=AccessToken;
}
返回结果;
}
专用异步任务GetAccessTokenAsync(CancellationToken CancellationToken)
{
//获取Azure SQL DB的访问令牌
变量资源=”https://database.windows.net/";
return await\u tokenProvider.GetAccessTokenAsync(资源,cancellationToken:cancellationToken);
}
}
可以这样添加:

//以某种方式检测环境(在本地您可能不想使用令牌)
var useManagedIdentity=true;
var managedEntityInterceptor=新的managedEntityConnectionInterceptor(UseManagedEntity);
services.AddDbContext(options=>options.UseSqlServer(connectionString.AddInterceptors(ManagedEntityInterceptor));
这样就不需要在构造函数中进行任何更改。 拦截器将在打开到SQL DB的连接之前获取令牌。 此外,我们还避免在构造函数中执行异步同步。
请注意,这需要EF Core 3.x.

您可以使用
UseSqlServer
重载
DbConnection
参数并传递配置的
SqlConnection
对象:

var sqlConnectionString = localConfig["SqlConnectionString"];
services.AddDbContext<MyDBContext>(
    options => options.UseSqlServer(new SqlConnection(sqlConnectionString)
    {
        AccessToken = (new Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result
    },
    sqlServerOptions => { sqlServerOptions.CommandTimeout(1000); }));
var sqlConnectionString=localConfig[“sqlConnectionString”];
services.AddDbContext(
options=>options.UseSqlServer(新的SqlConnection(sqlConnectionString)
{
AccessToken=(新的Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync(“https://database.windows.net/1.结果
},
sqlServerOptions=>{sqlServerOptions.CommandTimeout(1000);});

令牌将在几个小时后过期,因此需要每隔几个小时重新启动一次应用程序:\@juunas只要db上下文是短期的(这是AspNet.Core应用程序的常见情况),这应该不会是问题。但是我想你的解决方案总的来说是更好的,如果有现成的东西就好了。你的解决方案在启动时会得到一次令牌。然后它会在某个时候停止工作。@juunas当然(我感到羞耻)!但它本不打算这么做,现在也没有:)谢谢你@juunas。这看起来是一个很好的解决方案。唯一的问题是我使用的是EF2.x。我应该在我的问题中提到这一点。对:\2.2有一些版本的拦截器,如果我没记错的话,但我从来没有在那里实现过。@AbuShokry所以最后你会找到我的解决方案:)哪一个btw与你当前的构造函数逻辑完全相同。@IvanStoev如何?在这里,您似乎正在创建一个新的SQL连接实例。而我的解决方案(如MS文档)将令牌注入到已经建立的连接中,我不需要管理或处置该连接。我担心您的解决方案会在某个时候导致连接耗尽。我能读到对您的解决方案的任何引用吗?@AbuShokry摘自:“如果连接处于关闭状态,EF将根据需要打开和关闭连接。”。关闭是将物理连接返回到池