Что такое наиболее успешная практика для получения текущего имени пользователя на уровне доступа к данным?

Мы недавно добавили аудит к нашей базе данных. Коллега реализовал его с помощью триггеров и попросил, чтобы я назвал хранимую процедуру на входе в систему веб-сайта. Хранимая процедура вставляет текущее имя пользователя и текущий идентификатор сессии оракула в таблице так, чтобы триггер мог отобразить идентификатор сессии на имя пользователя. Проблема (или был), что он предполагал что интернет-сессия пользователя, отображенная на сессии базы данных. Дело не в этом, и мы используем организацию пула подключений, таким образом, идентификаторы сессии оракула могут отобразиться на многих пользователей, не обязательно пользователя, который вошел в систему на той сессии. Таким образом, я создал служебный метод на своем уровне доступа к данным, который называет его процедуру по каждой вставке, обновлению, и удалите (обеспечение, это находится в той же транзакции):

/// <summary>
/// Performs an insert, update or delete against the database
/// </summary>
/// <param name="transaction"></param>
/// <param name="command">The command.</param>
/// <param name="transaction">A transaction, can be null. 
/// No override provided without a transaction, to remind developer to always consider transaction for inserts, updates and deletes</param>
/// <returns>The number of rows affected by the operation</returns>
public static int InsertUpdateDelete(OracleCommand command, OracleTransaction transaction)
{
  if (command == null)
    throw new ArgumentNullException("command", "command is null.");

  OracleConnection connection = null;
  bool doCommit = false;
  try
  {
    if (transaction == null)
    {
      //We always need a transaction for the audit insert
      connection = GetOpenConnection();
      transaction = connection.BeginTransaction();
      doCommit = true;
    }

    command.Transaction = transaction;
    command.Connection = transaction.Connection;

    //TODO HttpContext requires that presentation layer is a website. So this call should NOT be in the data access layer.
    string username = HttpContext.Current.User.Identity.Name;
    if (!String.IsNullOrEmpty(username))
      pInsertCurrentUserForAudit(username, command.Transaction);

    int recordsAffected = command.ExecuteNonQuery();

    if (doCommit)
      transaction.Commit();

    return recordsAffected;
  }
  finally
  {
    if (doCommit)
    {
      if (transaction != null)
        transaction.Dispose();
      if (connection != null)
        connection.Dispose();
    }
  }
}

Это работает, и аудит теперь работает как требуется. Однако мне не нравится вызов к HttpContext:

string username = HttpContext.Current.User.Identity.Name;

Это был самый быстрый способ реализовать задачу, но я не думаю, что это должно быть на Уровне доступа к данным. Что, если в некоторое неизвестное время в будущем я хотел получить доступ к базе данных с помощью приложения форм? Я получил бы ошибку, когда я получаю доступ к HttpContext? Существует ли лучший способ добраться до имени пользователя, которое правильно разделяет проблемы? При передаче имени пользователя в в качестве параметра к каждой вставке, обновите и удалите, опция, но это будет долгая задача, и я задавался вопросом, был ли более изящный способ сделать его.

5
задан Colin 30 December 2009 в 15:42
поделиться

1 ответ

То, что вы сделали, определенно не лучший подход, (как вы описали выше в своем вопросе) Это одна из тех вещей, которые называются сквозными вопросами - другие вещи похожи на протоколирование, и т.д.)

Один из применяемых подходов заключается в том, чтобы передать вокруг контекстного объекта , который реализует функциональность для всех таких сквозных задач, так что каждый метод в каждом слое не нуждается в модификации для передачи данных, необходимых для реализации требуемой функциональности.

В противном случае, как вы предлагаете, вам придется передавать имя пользователя на уровень данных сверху в стек в каждом методе, который в этом нуждается. Если возможно, то один из вариантов - ввести базовый класс для всех таких методов (все методы уровня данных) и поместить этот метод в этот базовый класс....

3
ответ дан 15 December 2019 в 06:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: