偶然发现了Oracle 10g以后可用的新ClientId(又名client_identifier)变量,并希望将其纳入应用程序以协助审计跟踪。
应用程序正在使用生成的基于企业库DAAB的层(netTiers)连接到使用带有EntLibContrib的ODP.NET驱动程序,因此CRUD函数创建OracleDatabase对象,然后从中检索通用DbCommand对象
看起来OracleConnection类具有ClientId属性,那么在该模式中获取Connection对象的最简洁方法是什么?我是否应该从每个DbCommand中获取连接,我在那里创建并设置它,或者是否有点矫枉过正?
因为EntLib在幕后进行了大量的连接管理,所以我不确定是否可以将ClientId设置在CRUD函数之外的某个地方,并期望它能够持续存在?
答案 0 :(得分:0)
如果连接是部分类,则可以实现触发器,只要连接将状态更改为打开,就会设置客户端ID。 这就是我实施它的方式。
我不知道你是否可以使用其中的一部分:
public partial class DataContext
{
partial void OnContextCreated()
{
if ( null == this.Connection ) return;
this.Connection.StateChange += Connection_StateChange;
}
private EntityConnection EntityConnection
{
get { return this.Connection as EntityConnection; }
}
private OracleConnection OracleConnection
{
get { return this.EntityConnection.StoreConnection as OracleConnection; }
}
private void Connection_StateChange( object sender, StateChangeEventArgs e )
{
if ( e.CurrentState != ConnectionState.Open ) return;
OracleConnection conn = this.OracleConnection;
if ( null == conn ) return;
//closes connection on DataContext (bug?), and passes closed/broken connection
//conn.ClientId = HttpContext.Current == null ? "Anonymous" : HttpContext.Current.Profile.UserName;
//working solution
string identity = HttpContext.Current == null ? "Anonymous" : HttpContext.Current.Profile.UserName;
OracleCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "DBMS_SESSION.SET_IDENTIFIER";
cmd.Parameters.Add( new OracleParameter { ParameterName = "client_id", Value = identity } );
cmd.ExecuteNonQuery();
cmd.Dispose();
return;
}
protected override void Dispose( bool disposing )
{
if ( null != this.Connection )
this.Connection.StateChange -= Connection_StateChange;
base.Dispose( disposing );
}
}