当我尝试使用sp_setapprole在SqlConnection上设置应用程序角色时,我有时会在Windows事件日志中收到以下错误...
连接已被删除,因为打开它的主体随后假定了一个新的安全上下文,然后尝试在其模拟的安全上下文下重置连接。不支持此方案。请参阅联机丛书中的“模拟概述”。)
...我的应用程序中抛出了匹配的异常。
这些是池连接,有时连接池与app角色不兼容 - 事实上,Microsoft的旧建议是disable connection pooling(!!),但引入了sp_unsetapprole现在(理论上)可以在将连接返回池之前清理连接。
我相信这些错误发生在(由于未知原因)sp_unsetapprole在连接关闭并返回到连接池之前未在连接上运行时。然后,当从池返回此连接时,sp_approle注定会失败。
我可以捕获并处理此异常,但我更愿意检测即将发生的故障并完全避免异常(以及事件日志中的消息)。
是否可以在不引起异常的情况下检测问题?
欢迎提出想法或建议。
答案 0 :(得分:1)
这是逻辑上的,并没有太多使用sp_setapprole的经验但是在调用之前是否无法检查安全上下文?或者首先检查安全权限和上下文?
答案 1 :(得分:1)
看起来你正在调用sp_setapprole但是没有调用sp_unsetapprole然后让连接只返回池。
我建议使用一个结构(或类,如果你必须在方法中使用它)和IDisposable的实现,它将为你处理这个:
public struct ConnectionManager : IDisposable
{
// The backing for the connection.
private SqlConnection connection;
// The connection.
public SqlConnection Connection { get { return connection; } }
public void Dispose()
{
// If there is no connection, get out.
if (connection == null)
{
// Get out.
return;
}
// Make sure connection is cleaned up.
using (SqlConnection c = connection)
{
// See (1). Create the command for sp_unsetapprole
// and then execute.
using (SqlCommand command = ...)
{
// Execute the command.
command.ExecuteNonQuery();
}
}
}
public ConnectionManager Release()
{
// Create a copy to return.
ConnectionManager retVal = this;
// Set the connection to null.
retVal.connection = null;
// Return the copy.
return retVal;
}
public static ConnectionManager Create()
{
// Create the return value, use a using statement.
using (ConnectionManager cm = new ConnectionManager())
{
// Create the connection and assign here.
// See (2).
cm.connection = ...
// Create the command to call sp_setapprole here.
using (SqlCommand command = ...)
{
// Execute the command.
command.ExecuteNonQuery();
// Return the connection, but call release
// so the connection is still live on return.
return cm.Release();
}
}
}
}
客户端代码如下所示:
using (ConnectionManager cm = ConnectionManager.Create())
{
// Get the SqlConnection for use.
// No need for a using statement, when Dispose is
// called on the connection manager, the connection will be
// closed.
SqlConnection connection = cm.Connection;
// Use connection appropriately.
}
答案 2 :(得分:1)
不,这是不可能的。
答案 3 :(得分:1)
这有点脏,但如果您的原始用户拥有VIEW SERVER STATE
的权限,select * from sys.sysprocesses
将在角色未处于活动状态时返回所有进程,并在当前进程为单行时返回。< / p>