Сравнительный анализ хранимых процедур Oracle

#asp.net #.net #oracle #stored-procedures

#asp.net #.net #Oracle #хранимые процедуры

Вопрос:

Я .Веб-разработчик Net, работающий с устаревшей базой данных Oracle. В прошлом я работал с инструментами orm, такими как NHibernate, но вся связь с базой данных здесь должна выполняться с помощью хранимых процедур. Наш администратор базы данных просит нас передавать кучу административной информации для каждой вызываемой процедуры, включая имя пользователя / домен / ip конечного пользователя. Затем эти данные используются для вызова другой хранимой процедуры, которая регистрирует информацию об использовании при каждом вызове процедуры.

Я не очень хорошо разбираюсь в Oracle или Pl / Sql, и я пытаюсь написать свой.Чистый код в чистом виде, который соответствует лучшим практикам, когда это возможно. Мне кажется, что этот процесс передачи дополнительных данных в каждую процедуру является грязным и утомительным как для.Net и Oracle завершаются.

Кто-нибудь знает лучший способ достичь цели администратора базы данных без всех накладных расходов? Или это стандартный способ делать то, к чему я должен привыкнуть.

Комментарии:

1. Это определенно не стандартно и определенно не кажется хорошим способом сделать это. Какие «дополнительные» данные вам необходимо передать (например, имя пользователя и т. Д.)?

2. да, нам нужно передать имя пользователя, домен, IP-адрес.

Ответ №1:

Я бы использовал контекст, а не передавал дополнительные параметры для каждого вызова хранимой процедуры. Контекст — это удобное место для хранения произвольных данных о состоянии на уровне сеанса, на которые могут ссылаться все хранимые процедуры.

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

 SQL> create context myapp_ctx using ctx_pkg;

Context created.

SQL> create package ctx_pkg
  2  as
  3    procedure set_value( p_key in varchar2, p_value in varchar2 );
  4  end;
  5  /

Package created.

SQL> create package body ctx_pkg
  2  as
  3    procedure set_value( p_key in varchar2, p_value in varchar2 )
  4    as
  5    begin
  6      dbms_session.set_context( 'MYAPP_CTX', p_key, p_value );
  7    end;
  8  end;
  9  /

Package body created.
  

Когда приложение получает соединение из пула соединений, оно просто устанавливает всю контекстную информацию один раз.

 SQL> begin
  2    ctx_pkg.set_value( 'USERNAME', 'JCAVE' );
  3    ctx_pkg.set_value( 'IP_ADDRESS', '192.168.17.34' );
  4  end;
  5  /

PL/SQL procedure successfully completed.
  

Последующие вызовы и запросы в том же сеансе могут затем просто запрашивать любые значения, сохраненные в контексте.

 SQL> select sys_context( 'MYAPP_CTX', 'USERNAME' )
  2    from dual;

SYS_CONTEXT('MYAPP_CTX','USERNAME')
--------------------------------------------------------------------------------
JCAVE
  

На самом деле, вы почти наверняка захотите добавить clear_context в пакет процедуру, которая вызывается dbms_session.clear_context( 'MYAPP_CTX' ) для очистки любых значений, установленных в контексте, когда соединение было возвращено в пул соединений, чтобы избежать непреднамеренного переноса контекстной информации из одного сеанса в другой. Вероятно, вы также разработали бы пакет с отдельными процедурами для установки и получения по крайней мере общих ключей (имя пользователя, IP-адрес и т. Д.) Вместо того, Чтобы жестко указывать «ИМЯ пользователя» в нескольких местах. Я использовал один общий set_value метод просто для простоты.

Комментарии:

1. Возможно, я что-то упускаю, но, похоже, могут возникнуть потенциальные проблемы с параллелизмом, если несколько пользователей одновременно обращаются к сеансам. Например, что произойдет, если второй сеанс пользователя установит имя пользователя / ip, а затем первый сеанс пользователя вызовет хранимую процедуру, которая запрашивает имя пользователя. Не вернет ли он имя пользователя, установленное вторым сеансом?

2. @zaq — контекст (по умолчанию) является локальным для сеанса базы данных. Одновременно только один пользователь может использовать сеанс базы данных (хотя несколько сеансов среднего уровня могут совместно использовать сеанс базы данных с течением времени, когда они извлекают соединения из пула соединений). Вот почему вы обычно очищаете контекст, когда соединение было возвращено в пул подключений, когда соединение было извлечено из пула подключений или и то, и другое. Два сеанса базы данных будут иметь отдельные копии данных в своих соответствующих контекстах — один сеанс не будет видеть информацию в контексте другого сеанса.