Skip to content

7. Приклад використання з Firebird 2.1

7.1. Встановлення інструментів

Необхідно встановити такі інструменти:

  • SGBD: [http://www.firebirdsql.org/en/firebird-2-1-5/];
  • інструмент адміністрування: EMS, SQL Manager для InterBase/Firebird Freeware, [http://www.sqlmanager.net/fr/products/ibfb/manager/download].

У наведених нижче прикладах користувач — sysdba з паролем masterkey.

Запустимо Firebird, а потім інструмент [SQL Manager Lite for Firebird], за допомогою якого ми будемо адмініструвати SGBD.

  • у [1] ми запускаємо Firebird (SGBD) з меню «Пуск». Тут SGBD не було встановлено як службу Windows;
  • на [2] служба запущена. У правому нижньому куті екрана з’явилася іконка. Клацнувши на ній правою кнопкою миші, можна зупинити SGBD.

Тепер запускаємо утиліту [SQL Manager Lite for Firebird], за допомогою якої будемо керувати SGBD та [3].

  • у [4] ми створюємо нову базу;
  • у [5] підтверджуємо;
  • у [5], входимо під ім'ям SYSDBA / masterkey;
  • у [6] вказуємо місце розташування файлу, який буде створено. Адже база даних буде створена в одному файлі;
  • у [7] підтверджується завдання SQL, яке буде виконано;
  • у [8] база даних створена. Тепер її потрібно зберегти у [EMS Manager]. Інформація правильна. Виконуємо [OK];
  • у [9] ми входимо в систему;
  • у [10], [EMS Manager] відображає базу даних, яка наразі порожня.

Тепер ми підключимо до цієї бази даних проект VS 2012.

7.2. Створення бази даних на основі об’єктів

Почнемо з дублювання папки проєкту [RdvMedecins-SqlServer-01] у [RdvMedecins-Firebird-01] та [1]:

  • у [2], у VS 2012 видаляємо проект [RdvMedecins-SqlServer-01] із рішення;
  • у [3] проект було видалено;
  • у [4] додаємо ще один. Цей проект міститься в папці [RdvMedecins-Firebird-01], яку ми створили раніше;
  • у [5] завантажений проект має назву [RdvMedecins-SqlServer-01];
  • у [6] змінюємо його назву на [RdvMedecins-Firebird-01]
  • у [7] до розв’язання додають ще один проєкт. Він міститься у папці [RdvMedecins-SqlServer-01] того проєкту, який ми раніше видалили з розв’язання;
  • у [8] проект [RdvMedecins-SqlServer-01] знову включено до рішення.

Проєкт [RdvMedecins-Firebird-01] ідентичний проєкту [RdvMedecins-SqlServer-01]. Нам потрібно внести кілька змін. У [App.config] ми змінимо рядок підключення, а [DbProviderFactory] потрібно адаптувати до кожного SGBD.


<!-- рядок підключення до бази даних -->
  <connectionStrings>
    <add name="monContexte" connectionString="User=SYSDBA;Password=masterkey;Database=D:\data\istia-1213\c#\dvp\Entity Framework\databases\firebird\RDVMEDECINS-EF.GDB;DataSource=localhost;
Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;" providerName="FirebirdSql.Data.FirebirdClient" />
  </connectionStrings>
  <!-- фабрика провайдерів -->
  <system.data>
    <DbProviderFactories>
      <add name="Firebird Client Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=2.7.7.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c" />
    </DbProviderFactories>
  </system.data>
  • рядок 3: ім’я користувача та його пароль, а також повний шлях до бази даних Firebird;
  • рядки 8–10: файл DbProviderFactory. У рядку 9 згадується файл DLL [FirebirdSql.Data.FirebirdClient], якого у нас немає. Його можна отримати за допомогою NuGet та [1]:
  • у [2] у полі пошуку вводимо ключове слово firebird;
  • у [3] виберіть пакет [Firebird ADO.NET Data Provider]. Це коннектор ADO.NET для Firebird;
  • у [4] — новий номер;
  • у [5], у [App.config] потрібно вказати правильну версію DLL. Її можна знайти у властивостях.

У файлі [Entites.cs] потрібно адаптувати схему таблиць, які будуть згенеровані:


  [Table("MEDECINS")]
  public class Medecin : Personne
  {...}

  [Table("CLIENTS")]
  public class Client : Personne
  {...}

  [Table("CRENEAUX")]
  public class Creneau
  {...}

  [Table("RVS")]
  public class Rv
  {...}

У цьому випадку таблиці не мають схеми.

Налаштовуємо виконання проекту:

  • у [1] ми присвоюємо іншу назву збірці, яка буде згенерована;
  • у [2] також задаємо інший простір імен за замовчуванням;
  • у [3] вказуємо програму, яку потрібно виконати.

На цьому етапі помилок компіляції немає. Запустимо програму [CreateDB_01]. Отримуємо таке виключення:

Exception non gérée : System.Data.MetadataException: Le schéma spécifié n'est pas valide. Erreurs :
(11,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(23,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(33,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(43,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
   à System.Data.Metadata.Edm.StoreItemCollection.Loader.ThrowOnNonWarningErrors
()
   ...
   à RdvMedecins_01.CreateDB_01.Main(String[] args) dans d:\data\istia-1213\c#\d
vp\Entity Framework\RdvMedecins\RdvMedecins-Oracle-01\CreateDB_01.cs:ligne 15

Ми пам’ятаємо, що така сама помилка траплялася з MySQL, Oracle та PostgreSQL. Це пов’язано з типом поля Timestamp в сутностях. Ми вносимо ті самі зміни, що й у двох попередніх SGBD. В об’єктах ми замінюємо три рядки


    [Column("TIMESTAMP")]
    [Timestamp]
    public byte[] Timestamp { get; set; }

на такі:


    [ConcurrencyCheck]
    [Column("VERSIONING")]
    public int? Versioning { get; set; }

Отже, змінюємо тип стовпця з byte[] на int?. У SGBD ми будемо використовувати збережені процедури, щоб збільшувати це ціле число на одиницю щоразу, коли буде вставлено або змінено рядок.

Вносимо зазначену вище зміну для всіх чотирьох об’єктів, а потім запускаємо програму знову. У результаті отримуємо таку помилку:

1
2
3
4
5
Exception non gérée : FirebirdSql.Data.FirebirdClient.FbException: lock time-out on wait transaction object D:\DATA\ISTIA-1213\C#\DVP\ENTITY FRAMEWORK\DATABASES\FIREBIRD\RDVMEDECINS-EF.GDB використовується ---> FirebirdSql.Data.Common.IscException: перевищено час очікування блокування транзакції
object D:\DATA\ISTIA-1213\C#\DVP\ENTITY FRAMEWORK\DATABASES\FIREBIRD\RDVMEDECINS
-EF.GDB is in use
...
   à RdvMedecins_01.CreateDB_01.Main(String[] args) dans d:\data\istia-1213\c#\dvp\Entity Framework\RdvMedecins\RdvMedecins-Firebird-01\CreateDB_01.cs:рядок 15

У рядку 1 вказано, що база даних використовується. Наскільки я пам’ятаю, це не було так, і мені не вдалося вирішити цю проблему.

Неважливо. Ми створимо базу даних [RDVMEDECINS-EF] вручну за допомогою інструменту [EMS Manager for Firebird]. Ми не описуємо всі етапи, а лише найважливіші.

База даних Firebird матиме такий вигляд:

Таблиці

  • у [1], ID є первинним ключем з атрибутом Autoincrement. Вона буде автоматично згенерована інструментом SGBD;

Різні таблиці мають ті самі первинні та зовнішні ключі, що й у попередніх прикладах. Зовнішні ключі мають атрибути ON, DELETE та CASCADE.

Генератори

Як і у випадку з Oracle та PostgreSQL, ми створили генератори послідовних чисел. Їх є 5: [1].

  • [CLIENTS_ID_GEN] використовуватиметься для генерації первинного ключа таблиці [CLIENTS];
  • [MEDECINS_ID_GEN] буде використовуватися для генерації первинного ключа таблиці [MEDECINS];
  • [CRENEAUX_ID_GEN] буде використано для генерації первинного ключа таблиці [CRENEAUX];
  • [RVS_ID_GEN] буде використано для генерації первинного ключа таблиці [RVS];
  • [VERSIONS_GEN] буде використовуватися для генерації значень стовпців [VERSIONING] у всіх таблицях.

Тригери

Тригер — це процедура, що виконується SGBD до або після події (вставлення, зміна, видалення) у таблиці. У нас їх 8 [1]:

Розглянемо код DDL тригера [BI_CLIENTS_ID], який заповнює стовпець [ID] таблиці [CLIENTS]:

1
2
3
4
5
6
7
8
CREATE TRIGGER BI_CLIENTS_ID FOR CLIENTS
ACTIVE BEFORE INSERT
POSITION 0
AS
BEGIN
  IF (NEW.ID IS NULL) THEN
      NEW.ID = GEN_ID(CLIENTS_ID_GEN, 1);
END^
  • рядок 2: перед кожним вставленням у таблицю [CLIENTS];
  • рядки 6–7: якщо стовпець ID дорівнює NULL, то йому присвоюється наступне значення генератора чисел [CLIENTS_ID_GEN].

Усі тригери [ BI_CLIENTS_ID, BI_MEDECINS_ID, BI_CRENEAUX_ID, BI_RVS_ID] побудовані за однаковим принципом.

Тепер розглянемо код DDL тригера [CLIENTS_VERSION_TRIGGER], який заповнює стовпець [VERSIONING] таблиці [CLIENTS]:

1
2
3
4
5
6
7
CREATE TRIGGER CLIENTS_VERSION_TRIGGER FOR CLIENTS
ACTIVE BEFORE INSERT OR UPDATE
POSITION 1
AS
BEGIN
  NEW."VERSIONING" = GEN_ID(VERSIONS_GEN,1);
END^
  • рядки 1–3: перед кожною операцією INSERT або UPDATE над таблицею [CLIENTS];
  • рядок 6: стовпець ["VERSIONING"] отримує наступне значення від генератора чисел [VERSIONS_GEN]. Цей генератор заповнює стовпці ["VERSIONING"] у всіх чотирьох таблицях.

Тригери [MEDECINS_VERSION_TRIGGER, CRENEAUX_VERSION_TRIGGER, RVS_VERSION_TRIGGER] працюють аналогічно.

Скрипт для генерації таблиць бази даних Firebird [RDVMEDECINS-EF] розміщено у папці [RdvMedecins / databases / Firebird]. Читач може завантажити та виконати його для створення своїх таблиць.

Після цього можна запускати різні програми проекту. Вони дають ті самі результати, що й із сервером SQL, за винятком програми [ModifyDetachedEntities], яка вилітає з тієї самої причини, що й у випадку з Oracle та MySQL. Проблему вирішують таким самим чином. Достатньо скопіювати програму [ModifyDetachedEntities] із проєкту [RdvMedecins-Oracle-01] у проєкт [RdvMedecins-Firebird-01].

7.3. Багаторівнева архітектура на основі EF 5

Повернемося до нашого прикладу, описаного в розділі 2.

Почнемо з побудови шару [DAO] для доступу до даних. Для цього ми дублюємо консольний проєкт VS 2012 [RdvMedecins-SqlServer-02] у [RdvMedecins-Firebird-02] [1]:

  • у [2] видаляємо проект [RdvMedecins-SqlServer-02];
  • у [3] додаємо існуючий проект до рішення. Беремо його з папки [RdvMedecins-Firebird-02], яку щойно створили;
  • у [4] новий проєкт має назву того, що було видалено. Ми змінимо його назву;
  • у [5] ми змінили назву проєкту;
  • у [6] ми змінюємо деякі його властивості, наприклад, назву збірки;
  • у [7] папка [Models] видаляється, щоб її замінити папкою [Models] з проєкту [RdvMedecins-Firebird-01]. Адже обидва проєкти використовують однакові шаблони.
  • у [8] — поточні посилання проекту;
  • у [9] за допомогою інструменту NuGet додано коннектор ADO.NET для Firebird.

У файлі [App.config] замінюємо дані бази SQL Server на дані бази Firebird. Їх можна знайти у файлі [App.config] проекту [RdvMedecins-Firebird-01]:


<!-- рядок підключення до бази даних -->
  <connectionStrings>
    <add name="monContexte" connectionString="User=SYSDBA;Password=masterkey;Database=D:\data\istia-1213\c#\dvp\Entity Framework\databases\firebird\RDVMEDECINS-EF.GDB;DataSource=localhost;
Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;" providerName="FirebirdSql.Data.FirebirdClient" />
  </connectionStrings>
  <!-- фабричний провайдер -->
  <system.data>
    <DbProviderFactories>
      <add name="Firebird Client Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=2.7.7.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c" />
    </DbProviderFactories>
  </system.data>

Об’єкти, що керуються Spring, також змінюються. Наразі маємо:


  <!-- конфігурація Spring -->
  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <objects xmlns="http://www.springframework.net">
      <object id="rdvmedecinsDao" type="RdvMedecins.Dao.Dao,RdvMedecins-SqlServer-02" />
    </objects>
</spring>

У рядку 7 вказано збірку проекту [RdvMedecins-SqlServer-02]. Тепер збірка має назву [RdvMedecins-Firebird-02].

Тепер ми готові виконати тест шару [DAO]. Перед цим необхідно заповнити базу даних (програма [Fill] з проєкту [RdvMedecins-Firebird-01]). Тестова програма пройшла успішно.

Ми створюємо DLL для цього проєкту так само, як це було зроблено для проєкту [RdvMedecins-SqlServer-02], і збираємоусі файли DLL проекту в папку [lib], створену в [RdvMedecins-Firebird-02]. Це будуть посилання для веб-проекту [RdvMedecins-Firebird-03], який буде створено далі.

  

Тепер ми готові до створення шару [ASP.NET] нашого додатка:

Ми почнемо з проєкту [RdvMedecins-SqlServer-03]. Скопіюємо папку цього проєкту в [RdvMedecins-Firebird-03] та [1]:

  • у [2], за допомогою VS 2012 Express для веб-розробки відкриваємо рішення з папки [RdvMedecins-Firebird-03];
  • у [3] ми змінюємо як назву рішення, так і назву проєкту;
  • у [4] — поточні посилання проекту;
  • у [5] видаляємо їх;
  • на [6], щоб замінити їх посиланнями на DLL, які ми щойно зберегли у папці [lib] проекту [RdvMedecins-Firebird-02].

Залишилося лише змінити файл [Web.config]. Замінюємо його поточний вміст на вміст файлу [App.config] з проєкту [RdvMedecins-Firebird-02]. Зробивши це, запускаємо веб-проєкт. Він працює. Не забуваємо заповнити базу даних перед запуском веб-додатку.