There is a need from a customer to log every data change to a logging table with the actual user who made the modification. The application is using one SQL user to access t
Simply force an execution of the SET CONTEXT_INFO by using your DbContext or ObjectContext:
...
FileMoverContext context = new FileMoverContext();
context.SetSessionContextInfo(Environment.UserName);
...
context.SaveChanges();
FileMoverContext inherits from DbContext and has a SetSessionContextInfo method. Here is what my SetSessionContextInfo(...) looks like:
public bool SetSessionContextInfo(string infoValue)
{
try
{
if (infoValue == null)
throw new ArgumentNullException("infoValue");
string rawQuery =
@"DECLARE @temp varbinary(128)
SET @temp = CONVERT(varbinary(128), '";
rawQuery = rawQuery + infoValue + @"');
SET CONTEXT_INFO @temp";
this.Database.ExecuteSqlCommand(rawQuery);
return true;
}
catch (Exception e)
{
return false;
}
}
Now you just set up a database trigger which can access the CONTEXT_INFO() and set a database field using it.
Thanks for pointing me in the right direction. However, in my case, I also need to set the context info when doing select statements, because I am querying views that use the context info to control row-level security by user.
I found it easiest to attach to the StateChanged event of the connection and just watch for the change from not-open to open. Then I call the proc that sets context and it works every time, even if EF decides to reset the connection.
private int _contextUserId;
public void SomeMethod()
{
var db = new MyEntities();
db.Connection.StateChange += this.Connection_StateChange;
this._contextUserId = theCurrentUserId;
// whatever else you want to do
}
private void Connection_StateChange(object sender, StateChangeEventArgs e)
{
// only do this when we first open the connection
if (e.OriginalState == ConnectionState.Open ||
e.CurrentState != ConnectionState.Open)
return;
// use the existing open connection to set the context info
var connection = ((EntityConnection) sender).StoreConnection;
var command = connection.CreateCommand();
command.CommandText = "proc_ContextInfoSet";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("ContextUserID", this._contextUserId));
command.ExecuteNonQuery();
}