I want to have some information available for any stored procedure, such as current user. Following the temporary table method indicated here, I have tried the following:
1) create temporary table when connection is opened
private void setConnectionContextInfo(SqlConnection connection)
{
if (!AllowInsertConnectionContextInfo)
return;
var username = HttpContext.Current?.User?.Identity?.Name ?? "";
var commandBuilder = new StringBuilder($@"
CREATE TABLE #ConnectionContextInfo(
AttributeName VARCHAR(64) PRIMARY KEY,
AttributeValue VARCHAR(1024)
);
INSERT INTO #ConnectionContextInfo VALUES('Username', @Username);
");
using (var command = connection.CreateCommand())
{
command.Parameters.AddWithValue("Username", username);
command.ExecuteNonQuery();
}
}
/// <summary>
/// checks if current connection exists / is closed and creates / opens it if necessary
/// also takes care of the special authentication required by V3 by building a windows impersonation context
/// </summary>
public override void EnsureConnection()
{
try
{
lock (connectionLock)
{
if (Connection == null)
{
Connection = new SqlConnection(ConnectionString);
Connection.Open();
setConnectionContextInfo(Connection);
}
if (Connection.State == ConnectionState.Closed)
{
Connection.Open();
setConnectionContextInfo(Connection);
}
}
}
catch (Exception ex)
{
if (Connection != null && Connection.State != ConnectionState.Open)
Connection.Close();
throw new ApplicationException("Could not open SQL Server Connection.", ex);
}
}
2) Tested with a procedure which is used to populate a DataTable
using SqlDataAdapter.Fill
, by using the following function:
public DataTable GetDataTable(String proc, Dictionary<String, object> parameters, CommandType commandType)
{
EnsureConnection();
using (var command = Connection.CreateCommand())
{
if (Transaction != null)
command.Transaction = Transaction;
SqlDataAdapter adapter = new SqlDataAdapter(proc, Connection);
adapter.SelectCommand.CommandTimeout = CommonConstants.DataAccess.DefaultCommandTimeout;
adapter.SelectCommand.CommandType = commandType;
if (Transaction != null)
adapter.SelectCommand.Transaction = Transaction;
ConstructCommandParameters(adapter.SelectCommand, parameters);
DataTable dt = new DataTable();
try
{
adapter.Fill(dt);
return dt;
}
catch (SqlException ex)
{
var err = String.Format("Error executing stored procedure '{0}' - {1}.", proc, ex.Message);
throw new TptDataAccessException(err, ex);
}
}
}
3) called procedure tries to get the username like this:
DECLARE @username VARCHAR(128) = (select AttributeValue FROM #ConnectionContextInfo where AttributeName = 'Username')
but #ConnectionContextInfo
is no longer available in the context.
I have put a SQL profiler against the database, to check what is happening:
- temporary table is created successfully using a certain SPID
- procedure is called using the same SPID
Why is temporary table not available within the procedure scope?
In T-SQL doing the following works:
- create a temporary table
- call a procedure that needs data from that particular temporary table
- temporary table is dropped only explicitly or after current scope ends
Thanks.