Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

sql server+c++

.pdf
Скачиваний:
18
Добавлен:
07.06.2015
Размер:
2.12 Mб
Скачать

Порядок очищення від даних об’єкта DataSet:

1)таблиця Joint;

2)таблиця Students;

3)таблиці Groups, Schools, Hostels, Debts.

Програмний код буде виглядати так:

KSADataSet->Joint->Clear();

KSADataSet->Students->Clear();

KSADataSet->Groups->Clear();

KSADataSet->Schools->Clear();

KSADataSet->Hostels->Clear();

KSADataSet->Depts->Clear();

В. Обновлення даних: БД → DataSet.

Для отримання «свіжих» даних зі сервера об’єкт DataSet спершу необхідно очистити (п.Б), а потім знову заповнити даними (п.А). Порядок виконання цих двох етапів такий же, як у попередніх пунктах.

1)Очищення таблиць (Joint) → (Students) → (Groups, Schools, Hostels, Debts).

2)Заповнення таблиць (Groups, Schools, Hostels, Debts) → (Students) → (Joint).

Г. Обновлення даних: DataSet → БД.

Обновлення бази даних на сервері у відповідності до внесених змін у локальну базу об’єкта DataSet є складнішою процедурою, оскільки потрібно враховувати різні зміни (додавання, вилучення, зміна значення), які вносяться у локальну структуру реляційно зв’язаних даних.

 

PK

Primary

PK

Slave

 

 

 

 

 

знищити

Cod

Name

ID

Cod

знищити

A

Apple

1

A

 

B

Dog

2

A

знищити

додати

C

Bag

3

B

 

D

Cat

4

C

додати

 

 

 

5

D

FK

Рис. 4.65. Ілюстрація проблеми складного обновлення

79

При спробі передати обновлення у базу даних зі структурою, що зображена на рис. 4.65, виникають протиріччя – яку таблицю необхідно обновлювати першою.

Якщо спершу обновлювати Primary, а потім Slave, тоді сервер видасть помилку при спробі знищити стрічку в таблиці Primary, оскільки ще існують залежні від неї стрічки в таблиці Slave.

Якщо спробувати навпаки, тобто першою Slave, а потім Primary, то сервер теж видасть помилку, оскільки ми намагаємося вставити нові стрічки у таблицю Slave, для якої відсутні значення ключа у головній таблиці Primary.

Щоб вийти з цієї складної ситуації, необхідно передавати обновлення на сервер по частинах за таким алгоритмом:

1)додані стрічки у таблицю Primary, а потім у Slave;

2)змінені стрічки у таблиці Primary, а потім у Slave;

3)знищені стрічки у таблиці Slave, а потім у Primary.

Для реалізації обновлення по частинах, використовується метод Select() об’єкта DataTable, що дає можливість вибирати стрічки згідно заданих критеріїв: видалені, вставлені, обновлені.

Нехай для структури бази даних, зображеної на рис. 4.65, об’єкт моделі локальної бази має назву UpdateDataSet. Тоді програмний код для внесення обновлень у базу даних на сервері, який не порушує цілісності значень та забезпечує виконання усіх вищесказаних критеріїв для обновлення, буде мати такий вигляд:

this->Validate(); this->PrimaryBindingSource->EndEdit(); this->SlaveBindingSource->EndEdit(); DataViewRowState rs;

//передача доданих стрічок rs = DataViewRowState::Added; this->PrimaryTableAdapter->

Update(this->UpdateDataSet->Primary->Select("","",rs)); this->SlaveTableAdapter->

Update(this->UpdateDataSet->Slave->Select("","",rs));

//Передача змінених стрічок

rs = DataViewRowState::ModifiedCurrent; this->PrimaryTableAdapter->

Update(this->UpdateDataSet->Primary->Select("","",rs)); this->SlaveTableAdapter->

Update(this->UpdateDataSet->Slave->Select("","",rs));

80

//Передача знищених стрічок rs = DataViewRowState::Deleted; this->SlaveTableAdapter->

Update(this->UpdateDataSet->Slave->Select("","",rs)); this->PrimaryTableAdapter->

Update(this->UpdateDataSet->Primary->Select("","",rs));

Зауваження 1: при спробі передати серверу зміни значень ключового стовпця, що бере участь у зв’язку між таблицями (рис. 4.66), швидше за все згенерується помилка. Це може пояснюватися неправильною структурою БД.

 

PK

Primary

PK

Slave

 

 

 

 

 

 

Cod

Name

ID

Cod

 

 

A

Apple

1

A

 

змінити E

B

Dog

2

A

 

C

Bag

3

B

E автомат.

 

D

Cat

4

C

 

 

 

5

D

зміна

FK

Рис. 4.66. Обновлення значень ключового стовпця

Як правило, на рівні сервера для зв’язків між таблицями встановлюють правила видалення та обновлення за замовчуванням, тобто накладається заборона на усі зміни потенційного ключа, якщо існують зовнішні ключі, що посилаються на нього.

Якщо в об’єкті DataSet встановлено правило каскадного обновлення, тобто при зміні значення ключового стовпця автоматично зміниться значення зовнішнього ключа залежної таблиці (рис. 4.66), то при спробі передати зміни на сервер згенерується помилка обновлення з боку сервера. Сервер не може змінити значення ключового стовпця таблиці Primary, поки існують залежні стрічки в таблиці Slave, і відповідно, не може змінити значення у залежних стрічках на нові значення. Для виходу з цієї ситуації необхідно внести зміни у структуру БД.

1. Використання сурогатних ключів.

При використанні сурогатних ключів з автоінкрементом відпадає потреба в обновленні значень ключових стовпців (рис. 4.67).

81

Рис. 4.67. Зв’язування 2-х таблиць за автоінкрементним ключем

2. Застосування SET NULL стратегії.

Для виходу з проблемної ситуації цей підхід пропонує логічну розв’язку за допомогою правила обновлення SET NULL на стороні сервера та внесення незначних корекцій в об’єкт DataSet.

НА СЕРВЕРІ

а)

В ОБ’ЄКТІ DATASET

94

95

б)

82

96

98

97

 

в)

Рис. 4.68. Реалізація SET NULL стратегії

Уструктурі бази даних на сервері (рис. 4.68-а) для зв’язку між вказаними таблицями необхідно встановити правило обновлення SET NULL, правило видалення залишити за замовчуванням, тобто таке, що забороняє видалення, поки існують залежні стрічки. Стовпець зовнішнього ключа повинен дозволяти NULL-значення.

УSQL-сценарію правила видалення та обновлення будуть виглядати так:

ON DELETE NO ACTION

ON UPDATE SET NULL

В об’єкті DataSet у середовищі XSD-схеми (рис. 4.68-б) натиснути правою клавішею миші на зв’язку та в контекстному меню вибрати пункт Edit Relation. У вікні Relation пересвідчитися, що встанов-

лено режим Both Relation and Foreign Constraint та значення Cascade

для правила Update Rule.

Далі для таблиці Slave вибрати об’єкт TableAdapter (п. 96), у вікні Properties для команди обновлення вибрати параметр CommandText та справа від нього натиснути кнопку для редагування SQL-запиту на обновлення (п. 97).

83

У редакторі Query Builder витерти виділений фрагмент (п. 98), що містить перевірку для параметра @IsNull_<ім’я стовпця>. Після чого зберегти внесені зміни у XSD-схему.

Примітка: при реалізації зв’язку «багато до багатьох» SET NULL стратегія може бути реалізована лише при використанні стикувальної таблиці з додатковим сурогатним автоінкрементним стовпцем (рис. 4.69-а). При зв’язуванні таблиць зі стикувальною таблицею за сурогатними автоінкрементними ключами (рис. 4.69-б) відпадає потреба в обновленні ключових стовпців взагалі. Тому другий варіант реалізації зв’язку «багато до багатьох» є кращий для реалізації.

а)

б)

Рис. 4.69. Реалізації зв’язку «багато до багатьох»

Зауваження 2: є ще одна ситуація, що спричиняє помилку на стороні сервера. Вона пов’язана з видаленням стрічки в об’єкті DataSet та внесенням її точної копії назад у таблицю. При цьому DataSet буде містити 2 однакові стрічки: одна з них буде позначена, як видалена, а інша, як додана. При спробі передати обновлення по частинам на сервер за вибраною нами схемою додані змінені знищені стрічки сервер згенерує помилку обмеження первинного ключа. Це пов’язано з тим, що ми намагаємося спершу передати на сервер дублікат доданої стрічки (а така стрічка ще існує в БД сервера), а потім вилучити оригінал з БД сервера.

Висновок: розглянуті нами складні ситуації обновлення даних свідчать на користь використання сурогатних автоінкрементних ключів для зв’язування двох таблиць.

84

4.3.12. Розміщення стрічки підключення у зовнішньому файлі.

Для того, щоб програма-клієнт мала змогу працювати з базою даних з будь-якого комп’ютера мережі та не залежала від назви сервера чи налаштувань домену, необхідно мати можливість змінювати стрічку підключення. Найпростіший варіант – завантажувати її зі зовнішнього файлу.

Для цього потрібно додати на самому початку функції оброблення події завантаження форми відповідний код. Наприклад, для нашої бази даних КСА він буде виглядати так:

String^ line;

StreamReader^ SR = gcnew StreamReader( "ConnectionString" ); line = SR->ReadLine() ; SchoolsTableAdapter->Connection->ConnectionString = line; GroupsTableAdapter->Connection->ConnectionString = line; HostelsTableAdapter->Connection->ConnectionString = line; DeptsTableAdapter->Connection->ConnectionString = line; StudentsTableAdapter->Connection->ConnectionString = line; JointTableAdapter->Connection->ConnectionString = line;

Таким чином ми змінюємо значення параметра ConnectionString для кожного адаптера даних на значення, що розміщене у файлі "ConnectionString". Цей файл повинен розміщуватися разом з основним exe-файлом, а під час компіляції – знаходитися у папці поточного проекту.

Для об’єкту StreamReader обов’язково (у верхній частині поточного файлу) підключіть простір імен, в якому він розміщений:

using namespace System::IO;

Для того, щоб програма-клієнт запускалася на інших комп’юте-

рах, необхідно збудувати її у режимі Release .

На комп’ютерах, де має запускатися програма-клієнт, має бути також встановлена та сама версія (в тому числі і сервіс-пак) компо-

нентів .NET Framework.

85

5. Додаткові відомості.

Синтаксис обчислювальних виразів та фільтрів моделі ADO.NET

У моделі ADO.NET значення формул (Expression) для стовпців у XSD-схемі та значення для параметра фільтра (Filter) компоненти BindingSource мають синтаксис схожий до обчислювальних стовпців та логічних виразів конструкції WHERE мови SQL. Але є і деякі свої відмінності.

5.1. Назви стовпців у виразах ADO.NET.

Якщо у назві стовпця таблиці міститься спеціальний символ, тоді назву стовпця необхідно взяти у квадратні дужки. Це стосується також імен стовпців, назва яких розділена пробілом.

Total * [Sum-Year] – [V&D]*[Name#]

Спеціальні символи.

~ ( ) # \ / = > < + - * % & | ^ ' " [ ]

\n (нова стрічка) \t (табуляція) \r (повернення каретки)

Оскільки квадратні дужки теж є спеціальними символами, тоді для них в імені стовпця необхідно використовувати символ \.

Total * [Value[\]] (необхідно виділяти лише другу квадратну дужку)

5.2. Значення, що визначені користувачем.

Константні значення можуть використовуватися у виразах для порівняння зі значеннями стовпців. Значення стрічки та формату датичас повинні бути взяті в одинарні лапки. Для чисел дробова частина від цілої відокремлюється крапкою.

Surname = 'Vova'

Price <= 125.00

Birthdate > '27.11.2009' AND Birthdate < '28.11.2009'

5.3. Оператори.

AND, OR, NOT Стандартні булеві логічні операції. Використовуються для об’єднання декількох умов.

=, >, <, >=, <=, <>,

Операції порівняння.

IN, LIKE

 

86

 

+ (додавання)

Арифметичні операції.

-(віднімання)

*(множення)

/(ділення)

%(модуль)

+ (зчеплення стрічок) Оператор для конкатенації стрічок.

%Шаблонні символи оператора LIKE. Заміню-

*ють довільну кількість символів у стрічці. Шаблонні символи допустимі лише на початку або у кінці шаблону.

Surname LIKE 'Пав%' Surname LIKE '*ко'

 

Surname LIKE 'Па*чак'

(невірно!)

5.4. Функції.

 

 

 

CONVERT(expr, type)

Перетворює вираз expr у вказаний тип type

 

 

.NET Framework, наприклад, String, Int32,

 

Int64, UInt16, DateTime, Decimal і т.д.

 

Виключення: Boolean може бути перетворений

 

лише у/з String та цілочисельні типи. Char у/з

 

String, Int32, UInt32. DateTime у/з String.

 

Префікс System. у виразах є обов’язковим!

 

CONVERT(ID, 'System.String')+' '+Surname

 

CONVERT(ID,'System.String') LIKE '1%'

LEN(expr)

Повертає довжину стрічки expr.

 

'к-сть букв: '+LEN(Surname)

ISNULL(expr, reval)

Перевіряє вираз expr та повертає або переві-

 

рений вираз expr, або значення заміни reval,

 

якщо вираз рівний null.

 

 

 

total+ ISNULL(price, 0)

 

 

IIF(expr, truev, falsev)

Отримує одне з двох значень, у залежності від

 

результату логічного виразу expr.

 

truev – значення, якщо вираз повернув true.

 

falsev – значення, якщо вираз повернув false.

 

'результат: '+IIF(rating>70, 'добре', 'погано')

TRIM(expr)

Видаляє пробіли та пусті символи (\r, \n, \t) на

 

початку та в кінці стрічки (стовпця) expr.

 

 

87

 

SUBSTRING(expr, Отримує підстрічку вказаної довжини length, start, length) починаючи з позиції start у стрічці expr.

SUBSTRING(Nstud, 3, 4)

5.5. Статистичні функції для реляційного зв’язку.

Для поглибленого аналізу даних у моделі ADO.NET передбачено механізм статистичного оброблення даних у зв’язаних таблицях.

Між зв’язаними стрічками двох таблиць, для яких встановлено реляційний зв’язок, може відбуватися обмін даними. Для посилання у виразі на стовпець головної таблиці до його імені додається префікс

Parent. , наприклад, Parent.Name.

Для посилання на стовпець, що знаходиться у підлеглій таблиці, у виразі головної таблиці додається до імені префікс Child. Але оскільки підлегла таблиця може повернути декілька стрічок, то відповідно, стовпець підлеглої таблиці необхідно включати у статистичну функ-

цію, наприклад, SUM(Child.Price).

Якщо у таблиці є декілька підлеглих до неї таблиць, тоді префікс буде містити також і назву реляційного зв’язку Child(<ім’я звязку>). Для попереднього прикладу це буде виглядати так:

SUM(Child(FK_Details_Orders).Price)

Статистичні функції

SUM(<ім’я стовпця>)

Обчислює суму значень для групи значень.

AVG(<ім’я стовпця>)

Знаходить середнє арифметичне.

MIN(<ім’я стовпця>)

Повертає мінімальне значення.

MAX(<ім’я стовпця>)

Повертає максимальне значення.

COUNT(<ім’я стовпця>)

Повертає кількість стрічок у залежній групі.

STDEV(<ім’я стовпця>)

Обчислює статистичне середньоквадратич-

 

не відхилення.

VAR(<ім’я стовпця>)

Обчислює статистичну дисперсію.

 

 

Зауваження: при застосуванні статистичної функції для рідного стовпця таблиці у всіх стрічках таблиці будуть відображатися однакові значення, які є результатом дій цієї функції над усією групою значень цього стовпця.

88

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]