将 SqlDataReader 移至外部函数对性能有何影响?
Any performance implications of moving SqlDataReader to external function?
给定以下 SQLCLR 函数:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void ExecSQL(string sql, string connectionString)
{
WindowsIdentity clientId = null;
WindowsImpersonationContext impersonatedUser = null;
clientId = SqlContext.WindowsIdentity;
try
{
try
{
impersonatedUser = clientId.Impersonate();
if (impersonatedUser != null)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
//** HERE I WILL HAVE MULTIPLE VARIATIONS OF FETCHING THE SQLDATAREADER
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
SqlDataReader r = command.ExecuteReader();
impersonatedUser.Undo();
SqlContext.Pipe.Send(r);
}
}
else
{ throw new Exception("Impersonation failed."); }
}
finally
{
if (impersonatedUser != null) { impersonatedUser.Undo(); }
}
}
catch
{
throw;
}
}
移动此部分是否有任何性能或其他后果:
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
SqlDataReader r = command.ExecuteReader();
进入单独的 GetDataReader()
方法?
我问是因为我知道我要为许多不同的场景(Sql 文本、存储过程、Table 值函数、标量函数等)加载数据读取器,所以我我想将每个不同的实现封装到它们自己的函数中,而不是在这个函数中间有一个大的 switch 语句。
Are there any performance or other ramifications
不是我能想到的或运行成的。当然,当涉及到这种性质的与性能相关的问题时,我总是建议测试一下,看看哪个更好,因为任何人回答问题都可能是错误的,并且肯定存在“接受”答案不正确的情况。然而,您的系统上的软件 运行ning 是最终的答案:-)。
除此之外,还有一些关于问题中显示的代码片段的注释。
您可以将impersonatedUser.Undo();
移动到connection.Open();
之后。只需要建立连接。但是,话又说回来,将 Impersonation 处理保留在 main 方法中而不是仅将 Undo()
移动到新方法可能会更干净。
或者,您也可以将 connection.Open();
保留在此处的主要方法中。在任何一种情况下,您都必须传递 connection
对象。
您可以将 impersonatedUser = clientId.Impersonate();
包装在 if
条件中,测试 connectionString
以查看它是否是 "Context Connection = true;"
。这将允许您使用上下文连接,否则它将无法工作,因为它不能与模拟一起使用。我想您可以重新处理当前的 if (impersonatedUser != null)
,因为该测试将不再有效(新测试只关心 impersonatedUser
是否为 null
,如果上下文连接不是使用。
WindowsImpersonationContext
是一次性的,所以最好把你的finally
块移到外面的try
,然后在后面加上impersonatedUser.Dispose();
Undo()
.
给定以下 SQLCLR 函数:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void ExecSQL(string sql, string connectionString)
{
WindowsIdentity clientId = null;
WindowsImpersonationContext impersonatedUser = null;
clientId = SqlContext.WindowsIdentity;
try
{
try
{
impersonatedUser = clientId.Impersonate();
if (impersonatedUser != null)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
//** HERE I WILL HAVE MULTIPLE VARIATIONS OF FETCHING THE SQLDATAREADER
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
SqlDataReader r = command.ExecuteReader();
impersonatedUser.Undo();
SqlContext.Pipe.Send(r);
}
}
else
{ throw new Exception("Impersonation failed."); }
}
finally
{
if (impersonatedUser != null) { impersonatedUser.Undo(); }
}
}
catch
{
throw;
}
}
移动此部分是否有任何性能或其他后果:
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
SqlDataReader r = command.ExecuteReader();
进入单独的 GetDataReader()
方法?
我问是因为我知道我要为许多不同的场景(Sql 文本、存储过程、Table 值函数、标量函数等)加载数据读取器,所以我我想将每个不同的实现封装到它们自己的函数中,而不是在这个函数中间有一个大的 switch 语句。
Are there any performance or other ramifications
不是我能想到的或运行成的。当然,当涉及到这种性质的与性能相关的问题时,我总是建议测试一下,看看哪个更好,因为任何人回答问题都可能是错误的,并且肯定存在“接受”答案不正确的情况。然而,您的系统上的软件 运行ning 是最终的答案:-)。
除此之外,还有一些关于问题中显示的代码片段的注释。
您可以将
impersonatedUser.Undo();
移动到connection.Open();
之后。只需要建立连接。但是,话又说回来,将 Impersonation 处理保留在 main 方法中而不是仅将Undo()
移动到新方法可能会更干净。或者,您也可以将
connection.Open();
保留在此处的主要方法中。在任何一种情况下,您都必须传递connection
对象。您可以将
impersonatedUser = clientId.Impersonate();
包装在if
条件中,测试connectionString
以查看它是否是"Context Connection = true;"
。这将允许您使用上下文连接,否则它将无法工作,因为它不能与模拟一起使用。我想您可以重新处理当前的if (impersonatedUser != null)
,因为该测试将不再有效(新测试只关心impersonatedUser
是否为null
,如果上下文连接不是使用。WindowsImpersonationContext
是一次性的,所以最好把你的finally
块移到外面的try
,然后在后面加上impersonatedUser.Dispose();
Undo()
.