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 і наведу свій код, заточений під мене.

А у нас тут можна отримати грант на тестовий період Яндекс.Хмари. Варто лише у полі «секретний пароль» запровадити «Хабр»