#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 — контекст (по умолчанию) является локальным для сеанса базы данных. Одновременно только один пользователь может использовать сеанс базы данных (хотя несколько сеансов среднего уровня могут совместно использовать сеанс базы данных с течением времени, когда они извлекают соединения из пула соединений). Вот почему вы обычно очищаете контекст, когда соединение было возвращено в пул подключений, когда соединение было извлечено из пула подключений или и то, и другое. Два сеанса базы данных будут иметь отдельные копии данных в своих соответствующих контекстах — один сеанс не будет видеть информацию в контексте другого сеанса.