C# & Oracle - нотатки на полях
Колись давно, дуже давно.
Компанія купила ліцензію на БД Oracle. Потім у цю компанію я працевлаштувався. Відповідно почавши просувати .Net «в маси». БД Oracle використовуються не в багатьох організаціях, але використовують. Як здійснити взаємодію з БД Oracle, використовуючи C#?
Обмовлюся заздалегідь, я не гуру Oracle; а так само не гуру гарного використання патернів, але я намагаюся і знаю де лежить пиріжок підходжу до питання філософськи, знаю що є, знаю, що я хочу, але використовую в необхідному мені ключі.
Але залишимо філософствування. Займемося завданням. Насамперед необхідно підготувати «середовище»: 1. Поставити клієнт Oracle, без якого взаємодію з БД не здійснити. 2. Налаштувати TNS для своїх потреб. 3. Створити проект у Visual Studio. 4. Додати reference на складанняSystem.Data.OracleClient.dll, за допомогою якої і «маніпулюватимемо» БД.
Підготуємо ґрунт, мабуть зробимо БД військкомату. У найпростішому випадку для цього вистачить однієї таблиці:
create table CONSCRIPT_INFO ( not null , FIRST_NAME VARCHAR2(128), LAST_NAME VARCHAR2(128), AGES NUMBER, GROWTH FLOAT , BIOGRAPHY CLOB, <>constraint PK_CONSCRIPT_INFO primary key (ID) );
Ідентифікатор, Ім'я, Прізвище, Вік, Зростання, Біографія. Вага нас не цікавить.
Визначимо процедури для додавання, на мій погляд найцікавіше, далі поясню чому:
PROCEDURE ADD_CONSCRIPT (FirstNameIn IN VARCHAR2, LastNameIn IN VARCHAR2, AgesIn IN NUMBER, GrowthIn IN FLOAT , BiographyIn IN CLOB ) IS BEGIN INSERT INTO CONSCRIPT_INFO ( ID, FIRST_NAME, LAST_NAME, AGES, GROWTH, BIOGRAPHY ) VALUES ( CONSCRIPT_INFO_SEQ.NEXTVAL, FirstNameIn, LastNameIn, AgesIn, GrowthIn, BiographyIn ); END;
PROCEDURE DELETE_CONSCRIPT (Conscript & INNUMBER) IS BEGIN
DELETE FROM CONSCRIPT_INFO WHERE > END;
PROCEDURE GET_CONSCRIPTS (ConscriptsOut OUT sys_refcursor) IS BEGIN
OPEN ConscriptsOut FOR SELECT * FROM CONSCRIPT_INFO;
Тепер я поясню, що цікавого в процедурі додавання нового користувача є об'єкт типу CLOB. Цей тип здатний зберігати рядкові дані розміром до 4 гігабайт, на відміну від Varchar, здатного оперувати рядками до 4000 байт. Тобто. якщо ви спробуєте створити VARCHAR поле розміром 5000, отримаєте суворий «облом». Але ті хто працював з типом CLOB з C# знають, що це дуже «челябенськи». Але я забігаю вперед, про все гаразд.
При роботі з Oracle є один неприємний момент, якщоявноне закривати з'єднання, то кількість курсорів після SELECT`a буде рости в геометричній прогресії. Ця проблема вирішується «в лоб»:
Створення та відкриття з'єднання
using (OracleConnection connection = новий OracleConnection()) . >
таким чином, за вас всю чорнову роботу зробить IDisposable. Якщо звернути увагу на конструкторOracleConnection, то побачите, що є 2 варіанти, «порожній» і з використанням рядка, що описує з'єднання з БД. Рядок має приблизно такий вигляд:Data Source=out_database_name;Password=our_password;User > Я думаю в поясненнях, що тут що, цей рядок не потребує.
Наступним кроком варто відкрити з'єднання:
Створення команди
Наразі ми готові виконувати команду. Після використання команди її теж необхідно «звільнити», не будемовідходити від принципів і скористаємося все тією ж чудовою конструкцієюusing:
using (OracleConnection connection = новий OracleConnection()) using (OracleCommand command = новий OracleCommand()) command.Connection = connection; command.CommandType = System.Data.CommandType.StoredProcedure; command.CommandText = "GET_CONSCRIPTS" ; > >
Давайте розберемося, що робить цей «шматок» коду: спочатку створюється команда, їй присвоюється з'єднання, в рамках якого працюватиме наша команда. Потім вказується тип команди, всього виділяється 3 типи: 1. StoredProcedure — Ім'я процедури, що зберігається. 2. TableDirect - Ім'я таблиці. 3. Text - Текстова команда SQL. (За замовчуванням).
Наступний параметр — текст, безпосередньо ім'я процедури, що зберігається, або команда. У нашому випадку буде використана процедура, що зберігається, з ім'ям«GET_CONSCRIPTS»
Використання параметрів, що передаються
Зазначу відразу, використовувати параметри можна і зCommandType.Text, нижче я покажу як це робиться.
Поки що повернемося з нашими параметрами:
OracleParameter ConscriptsOut = новий OracleParameter() ParameterName = "ConscriptsOut" , Direction = System.Data.ParameterDirection.Output, OracleType = OracleType.Cursor >;
Що відбувається тут: створили параметр, вказали що він працює на «вихід» і вказали тип параметра (докладнішу інформацію про типи, що використовуються, а також їх сумісності зі стандартними типами .Net можна дізнатися з MSDN). Якби параметр працював на «вхід», потрібно було б вказати і значення -Value. Прикріпили параметр до команди та…
Виконання команди
команда виконана ... тепер можна "вигрібти" дані наприклад так:
DataTable table = newDataTable(); table.Load(command.Parameters[ "ConscriptsOut" ].Value as OracleDataReader);
Параметр, що повертається, являє собою курсор, який можна прочитати, як OracleDataReader. Як розбирати параметр залишимо як «домашнє завдання» ;).
На коня
На закінчення, я хочу розповісти про те, як передати параметр у текст, а точніше я покажу:
using (OracleConnection connection = новий OracleConnection()) using (OracleCommand command = новий OracleCommand()) command.Connection = connection; command.CommandType = System.Data.CommandType.Text; command.CommandText = @"SELECT * FROM CONSCRIPT_INFO WHERE AGES ;
OracleParameter maxAges = new OracleParameter() ParameterName = "max_ages" , Direction = ParameterDirection.Input, OracleType = OracleType.Number, Value = 27 >;
OracleDataReader reader = command.ExecuteReader();
Як бачите вся хитрість полягає у використанні знака -:.
У наступній статті я розповім про роботу з CLOB і наведу свій код, заточений під мене.
А у нас тут можна отримати грант на тестовий період Яндекс.Хмари. Варто лише у полі «секретний пароль» запровадити «Хабр»