我们使用 asp.net core 3.x 和 EF Core 3.x
我们确实对几个实体有授权(因此它只允许表中的少数记录作为响应返回),这是通过访问 SQL 视图(内部连接两个表)实现的,我们针对该视图进行查询,该视图将只为您提供那些记录哪个登录用户被授权。
为了实现这一点,我们需要@@spid
在执行选择查询(在应用程序表上)之前将登录的用户 ID 和(SQL Server)插入表(会话)(在上面的视图中使用),并且我们需要在之后立即删除该记录查询被执行。为了实现这一点,我们正在使用DbInterceptor
.
会话表:
用户身份 | 会话 ID |
---|---|
1 | 32 |
2 | 26 |
应用表:
ID | 用户身份 | 文本 |
---|---|---|
1 | 1 | 我需要帮助... |
2 | 2 | 我不会说英文... |
db拦截器实现:
public class DbInterceptor : DbCommandInterceptor
{
private readonly IExecutionContext _executionContext;
public DbInterceptor(IExecutionContext executionContext)
{
_executionContext = executionContext;
}
public override async Task<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command,
CommandEventData eventData, InterceptionResult<DbDataReader> result,
CancellationToken cancellationToken = new CancellationToken())
{
var sqlParameter = new SqlParameter("UserId",
_executionContext.CurrentPrincipal.FindFirst(Claims.TSSUserId).Value);
await eventData.Context.Database.ExecuteSqlRawAsync("EXEC InsertUserSP @UserId", sqlParameter);
return await base.ReaderExecutingAsync(command, eventData, result);
}
public override async Task<DbDataReader> ReaderExecutedAsync(DbCommand command,
CommandExecutedEventData eventData, DbDataReader result,
CancellationToken cancellationToken = new CancellationToken())
{
var sqlParameter = new SqlParameter("UserId",
_executionContext.CurrentPrincipal.FindFirst(Claims.TSSUserId).Value);
await eventData.Context.Database.ExecuteSqlRawAsync("EXEC DeleteUserSP @UserId", sqlParameter);
return await base.ReaderExecutedAsync(command, eventData, result);
}
}
现在有了这个我们有一个例外
System.InvalidOperationException: '已经有一个打开的 DataReader 与此命令关联,必须先关闭。' 在线等待 eventData.Context.Database.ExecuteSqlRawAsync("EXEC DeleteUserSP @UserId", sqlParameter); 在拦截器的 `ReaderExecutedAsync` 方法中。
我用谷歌搜索了这个异常,发现可以通过MultipleActiveResultSets
在连接字符串中提供 true 来克服这个错误。
使用有副作用MultipleActiveResultSets
吗?
在浏览该主题时,我遇到了几篇文章,指出它可以在不同的请求之间共享连接实例,何时MultipleActiveResultSets
设置为 true。如果在实时请求线程之间共享相同的连接,那么它可能会出现问题,因为授权正在处理这样一个事实,即它@@spid
对于所有正在运行的实时线程都具有唯一性。
DbContext
连接池中的连接实例将如何提供?