gpt4 book ai didi

c# - 我可以在 Entity Framework Core 中触发连接数据库的事件吗?

转载 作者:行者123 更新时间:2023-11-29 12:09:45 25 4
gpt4 key购买 nike

我有一个 DbContext,所有这些都可以访问我的 Postgresql 数据库,但是当连接 session 从数据库开始时,我需要运行一个小的 SQL 命令。我需要为每次互动都这样做。更具体地说,它是一个设置 session 变量的函数,其中记录了用户名。

可以在 EF Core 中做一些事情来处理这个问题吗?

--解决方案--

我没有意识到我可以像 bricelam 说的那样直接在 OnConfiguring 中指定一个连接。我需要在每个连接中都这样做,因为它是 session 的变量。它不是数据库的用户名,而是应用程序日志系统的用户名。

    public ContratoInternetDbContext(DbContextOptions<ContratoInternetDbContext> options, 
IOptions<AppSettings> configs)
: base(options)
{
_appSettings = configs.Value;
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var conn = new NpgsqlConnection(_appSettings.ConnectionString);
conn.StateChange += (snd, e) =>
{
if ((e.CurrentState != e.OriginalState) && (e.CurrentState == ConnectionState.Open))
{
_cmmSetVarSession.ExecuteNonQuery();
}
};

optionsBuilder.UseNpgsql(conn);

_cmmSetVarSession = conn.CreateCommand();
_cmmSetVarSession.CommandText = "select sessao_set_var('usuario', 'CENTRAL_CLIENTE')";
}

最佳答案

如果您使用的是 EF Core 3.0 或更高版本,您现在可以使用 DBConnectionInterceptor为了这。执行您想要的操作的代码看起来像这样。

public class DbUserIdProvider : DbConnectionInterceptor
{
// Called just after EF has called Open().
public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)
{
base.ConnectionOpened(connection, eventData);
var cmd = connection.CreateCommand();
cmd.CommandText = "set session.client_user_id to 'myid'";
cmd.ExecuteNonQuery();
}

// Called just after EF has called OpenAsync().
public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "set session.client_user_id to 'myid'";
cmd.ExecuteNonQuery();
return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);
}
}

当您使用异步方法访问数据库时调用 ConnectionOpenedAsync()。

要连接此拦截器以便上下文了解它,您必须像这样将其添加到 Startup.cs 中的 AddDbContext 调用中。

services.AddDbContext<ApplicationDbContext>(options => options
.UseNpgsql(connection)
.AddInterceptors(new DbUserIdProvider()));

编辑:自从我写这篇文章以来,我找到了一种更好的方法来将拦截器添加到数据库上下文中。我现在是这样做的。

services.AddScoped<DbUserIdInterceptor>();

services.AddDbContext<ApplicationDbContext>((provider, options) =>
{
options.UseNpgsql(applicationSettings.ConnectionString());
// Resolve the DbUserIdInterceptor from the service provider
options.AddInterceptors(provider.GetRequiredService<DbUserIdInterceptor>());
});

这允许我在拦截器中为 DI 使用构造函数注入(inject),现在看起来像这样。

public class DbUserIdInterceptor : DbConnectionInterceptor
{
UserInfoService userInfoService;
public DbUserIdInterceptor(UserInfoService uis)
{
userInfoService = uis;
}

// Called just after EF has called OpenAsync().
public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)
{
var cmd = connection.CreateCommand();
cmd.CommandText = $"set session.client_user_id to '{userInfoService.uniqueName}'";
cmd.ExecuteNonQuery();
return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);
}
}

关于c# - 我可以在 Entity Framework Core 中触发连接数据库的事件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42587984/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com