2

我正在尝试在由 Oracle 数据库支持的 Web 应用程序中实现审计跟踪,当用户通过 SQL 客户端(如 TOAD)或当我手动使用 Oracle.DataAccess 更改数据时,我们确实有完美工作的审计跟踪触发器。客户通过

        // rest omitted for brevity // 

        var command = new OracleCommand();
        command.Connection = conn;


        var useridsql = new StringBuilder();

        useridsql.AppendLine("BEGIN");
        useridsql.AppendLine("dbms_session.set_identifier('username');");
        useridsql.AppendLine("END;");



        command.CommandText = useridsql.ToString();

        command.ExecuteNonQuery(); 
     // Rest of the insert / update / delete code // 

当我尝试通过覆盖 DbContext 类中的 SaveChanges() 来做同样的事情时,不起作用的是。

我假设实体使用与上述 ADO.NET 示例不同的方式来管理其连接,因此更新发生的原因是在错误的数据库会话上,因此 dbms_session 对触发器不可见。

我确实尝试关闭连接池,这也没有多大帮助。

我已经尝试了我知道的所有可能的情况,但没有任何成功。

这里有没有人有想法,可以把我推向正确的方向。

在此先感谢,非常感谢您的帮助。

亲切的问候,

最大限度。

4

2 回答 2

3

我也尝试了你所做的,但在跟踪中我可以看到 clientid 被重置为空字符串。这对我有用。

我的 DbContext

private SiSiEntities db = new SiSiEntities();

我认为在执行以下操作时,这将是一个不同的会话,但它可以工作。

OracleConnection conn = db.Database.Connection as Oracle.DataAccess.Client.OracleConnection;
conn.Open();
conn.ClientId = User.Identity.Name.ToString().ToLower(); 
db.SaveChanges();
于 2013-09-20T19:28:24.973 回答
0

在 Spring 中,您可以扩展TransactionAwareDataSourceProxy。您可以覆盖getConnection()方法并在获取连接时运行查询以将数据库会话分配给当前应用程序会话用户。当然,这仅在您使用跨国环境时才有意义。

为了提高效率,您还可以扩展 Connection 对象以使用当前会话用户的信息对其进行包装,以便仅在数据库会话用户与当前用户不同时才更新它。

一个简单的例子:

public class CustomTransactionAwareDataSourceProxy extends
        TransactionAwareDataSourceProxy {

    private static final SQL = "begin dbms_session.set_identifier(?); end;";

    public CustomTransactionAwareDataSourceProxy(
            final DataSource targetDataSource) {
        super(targetDataSource);
    }

    @Override
    public Connection getConnection() throws SQLException {
        return this.decorate(super.getConnection());
    }

    private Connection decorate(final Connection conn)
            throws SQLException {

            try (PreparedStatement statement = connection.prepareCall(SQL)) {
                statement.setString(1, this.getUsername());
                statement.execute();
            }
            return connection;
    }
}
于 2013-12-10T17:12:03.173 回答