Skip to content

7. Firebird 2.1 ile vaka çalışması

7.1. Araçların kurulumu

Yüklenecek araçlar şunlardır:

  • SGBD: [http://www.firebirdsql.org/en/firebird-2-1-5/];
  • bir yönetim aracı: EMS, SQL, InterBase/Firebird Freeware için Yönetici, [http://www.sqlmanager.net/fr/products/ibfb/manager/download].

Aşağıdaki örneklerde, kullanıcı sysdba ve şifresi masterkey'dir.

Firebird'ü başlatıp ardından [SQL Manager Lite for Firebird] aracını çalıştıralım; bu araçla SGBD'i yöneteceğiz.

  • [1]'te, Başlat Menüsü'nden SGBD Firebird'ü başlatıyoruz. Burada, SGBD bir Windows hizmeti olarak kurulmamıştır;
  • [2]'te hizmet başlatılmıştır. Ekranın sağ alt köşesine bir simge yerleştirilmiştir. Bu simgeye sağ tıklayarak SGBD'i durdurabiliriz.

Şimdi, SGBD ve [3]'i yönetmek için [SQL Manager Lite for Firebird] aracını başlatıyoruz.

  • [4]'te yeni bir veritabanı oluşturuyoruz;
  • [5]'te onaylıyoruz;
  • [5]'te, SYSDBA / masterkey olarak oturum açıyoruz;
  • [6]'te, oluşturulacak dosyanın konumunu belirleriz. Aslında, veritabanı tek bir dosya içinde oluşturulacaktır;
  • [7]'te, yürütülecek olan SQL komutunu onaylayın;
  • [8]'te veritabanı oluşturulmuştur. Şimdi [EMS Manager]'te kaydedilmelidir. Bilgiler doğrudur. [OK] komutunu veriyoruz;
  • [9]'e bağlanıyoruz;
  • [10]'te, [EMS Manager] veritabanını görüntüler; veritabanı şimdilik boştur.

Şimdi bu veritabanına bir VS 2012 projesini bağlayacağız.

7.2. Varlıklardan veritabanı oluşturma

İlk olarak, [RdvMedecins-SqlServer-01] proje klasörünü [RdvMedecins-Firebird-01] ve [1] klasörlerine kopyalayalım:

  • [2]'e kopyalıyoruz; VS 2012'de, [RdvMedecins-SqlServer-01] projesini çözümden siliyoruz;
  • [3]'te proje silinmiştir;
  • [4]'te, başka bir proje daha ekliyoruz. Bu proje, daha önce oluşturduğumuz [RdvMedecins-Firebird-01] klasöründen alınmıştır;
  • [5]'te yüklenen projenin adı [RdvMedecins-SqlServer-01]'tir;
  • [6]'e, adını [RdvMedecins-Firebird-01] olarak değiştiriyoruz
  • [7]'te, çözüme başka bir proje eklenir. Bu proje, daha önce çözümden sildiğimiz projenin [RdvMedecins-SqlServer-01] klasöründen alınır;
  • [8]'te, [RdvMedecins-SqlServer-01] projesi çözüme yeniden eklendi.

[RdvMedecins-Firebird-01] projesi, [RdvMedecins-SqlServer-01] projesiyle aynıdır. Birkaç değişiklik yapmamız gerekiyor. [App.config]'te bağlantı dizesini değiştireceğiz ve [DbProviderFactory]'i her bir SGBD'e uyarlamamız gerekiyor.


<!-- veritabanı bağlantı dizesi -->
  <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>
  <!-- fabrika sağlayıcısı -->
  <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. satır: kullanıcı adı ve şifre ile Firebird veritabanının tam yolu;
  • 8-10. satırlar: DbProviderFactory. 9. satır, elimizde olmayan bir DLL [FirebirdSql.Data.FirebirdClient] dosyasına atıfta bulunuyor. Bunu NuGet ve [1] ile elde edebiliriz:
  • [2]'e geldiğimizde, arama alanına firebird anahtar kelimesini yazıyoruz;
  • [3]'te, [Firebird ADO.NET Data Provider] paketini seçin. Bu, Firebird için bir ADO.NET bağlayıcısıdır;
  • [4]'e, yeni referans;
  • [5]'e, [App.config]'te DLL'in doğru sürümünü girmelisiniz. Bu bilgi, özellikler bölümünde bulunur.

[Entites.cs] dosyasında, oluşturulacak tabloların şemasını uyarlamak gerekir:


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

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

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

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

Burada tabloların şeması yoktur.

Projenin çalışmasını yapılandırıyoruz:

  • [1]'te, oluşturulacak derlemeye başka bir ad veriyoruz;
  • [2]'te, varsayılan olarak başka bir ad alanı belirliyoruz;
  • [3]'te, çalıştırılacak programı belirliyoruz.

Bu aşamada derleme hatası yok. [CreateDB_01] programını çalıştıralım. Aşağıdaki istisna ile karşılaşılır:

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 ve PostgreSQL ile de aynı hatayı aldığımızı hatırlıyoruz. Bu, varlıkların Timestamp alanının türüyle ilgilidir. Önceki iki SGBD örneğinde olduğu gibi aynı değişikliği yapıyoruz. Varlıklarda, şu üç satırı değiştiriyoruz:


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

şunlarla değiştiriyoruz:


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

Dolayısıyla sütunun türünü byte[]'den int? olarak değiştiriyoruz. SGBD'te, her satır eklendiğinde veya değiştirildiğinde bu tamsayıyı bir birim artırmak için saklı yordamlar kullanacağız.

Dört varlık için de yukarıdaki değişikliği yapıp uygulamayı yeniden çalıştırıyoruz. Bunun üzerine şu hata mesajıyla karşılaşıyoruz:

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 kullanımda ---> FirebirdSql.Data.Common.IscException: bekleme işlemi sırasında kilit zaman aşımı
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:satır 15

1. satır, veritabanının kullanıldığını gösteriyor. Sanırım durum böyle değildi ve bu sorunu çözemedim.

Neyse. [RDVMEDECINS-EF] veritabanını [EMS Manager for Firebird] aracıyla manuel olarak oluşturacağız. Tüm adımları değil, sadece en önemli olanları anlatacağız.

Firebird veritabanı şu şekilde olacaktır:

Tablolar

  • [1]'te, ID, Autoincrement özniteliğine sahip bir birincil anahtardır. Bu, SGBD tarafından otomatik olarak oluşturulacaktır;

Farklı tablolar, önceki örneklerdeki aynı tabloların sahip olduğu birincil ve yabancı anahtarlara sahiptir. Yabancı anahtarların öznitelikleri ON, DELETE ve CASCADE'tir.

Jeneratörler

Oracle ve PostgreSQL'te olduğu gibi, ardışık sayı üreteçleri oluşturduk. Bunların sayısı 5'tir: [1].

  • [CLIENTS_ID_GEN], [CLIENTS] tablosunun birincil anahtarını oluşturmak için kullanılacak;
  • [MEDECINS_ID_GEN], [MEDECINS] tablosunun birincil anahtarını oluşturmak için kullanılacak;
  • [CRENEAUX_ID_GEN], [CRENEAUX] tablosunun birincil anahtarını oluşturmak için kullanılacaktır;
  • [RVS_ID_GEN], [RVS] tablosunun birincil anahtarını oluşturmak için kullanılacaktır;
  • [VERSIONS_GEN], tüm tabloların [VERSIONING] sütunlarındaki değerleri oluşturmak için kullanılacaktır.

Tetikleyiciler

Tetikleyici, bir tabloda bir olay (Ekleme, Değiştirme, Silme) öncesinde veya sonrasında SGBD tarafından yürütülen bir yordamdır. 8 adet [1] tetikleyicimiz bulunmaktadır:

[CLIENTS] tablosunun [ID] sütununu dolduran [BI_CLIENTS_ID] tetikleyicisinin koduna bir göz atalım:

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. satır: [CLIENTS] tablosuna her ekleme işleminden önce;
  • 6-7. satırlar: ID sütunu NULL ise, ona [CLIENTS_ID_GEN] sayı üretecinin bir sonraki değeri atanır.

[ BI_CLIENTS_ID, BI_MEDECINS_ID, BI_CRENEAUX_ID, BI_RVS_ID] tetikleyicilerinin tümü aynı şekilde oluşturulmuştur.

Şimdi, [CLIENTS] tablosunun [VERSIONING] sütununu besleyen [CLIENTS_VERSION_TRIGGER] tetikleyicisinin DDL koduna bakalım:

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. satırlar: [CLIENTS] tablosunda her INSERT veya UPDATE işlemi öncesinde;
  • 6. satır: ["VERSIONING"] sütunu, [VERSIONS_GEN] sayı üreticisinden aşağıdaki değeri alır. Bu üretici, dört tablonun ["VERSIONING"] sütunlarını besler.

[MEDECINS_VERSION_TRIGGER, CRENEAUX_VERSION_TRIGGER, RVS_VERSION_TRIGGER] tetikleyicileri de benzerdir.

Firebird veritabanı tablolarını oluşturan [RDVMEDECINS-EF] komut dosyası, [RdvMedecins / databases / Firebird] klasörüne yerleştirilmiştir. Okuyucu, tablolarını oluşturmak için bu dosyayı yükleyip çalıştırabilir.

Bu işlem tamamlandıktan sonra, projenin çeşitli programları çalıştırılabilir. Bu programlar, SQL Sunucusu ile elde edilen sonuçların aynısını verir; ancak [ModifyDetachedEntities] programı, Oracle ve MySQL ile çöktüğü aynı nedenden dolayı çöker. Sorun aynı şekilde çözülür. [RdvMedecins-Oracle-01] projesindeki [ModifyDetachedEntities] programını [RdvMedecins-Firebird-01] projesine kopyalamak yeterlidir.

7.3. EF 5'e dayalı çok katmanlı mimari

2. paragrafta açıklanan vaka çalışmamıza geri dönüyoruz.

İlk olarak, veri erişim katmanı olan [DAO]'i oluşturacağız. Bunu yapmak için, VS 2012 konsol projesini [RdvMedecins-SqlServer-02]'te [RdvMedecins-Firebird-02] ve [1] olarak çoğaltıyoruz:

  • [2]'e kopyaladıktan sonra, [RdvMedecins-SqlServer-02] projesini siliyoruz;
  • [3]'e, çözüme mevcut bir proje eklenir. Bu proje, az önce oluşturulan [RdvMedecins-Firebird-02] klasöründen alınır;
  • [4]'te, yeni projenin adı silinen projenin adını taşıyor. Adını değiştireceğiz;
  • [5]'te, projenin adını değiştirdik;
  • [6]'e, bazı özelliklerini değiştiriyoruz, örneğin burada derleme adını;
  • [7]'e, [Models] klasörü silinip, [RdvMedecins-Firebird-01] projesindeki [Models] klasörü ile değiştiriliyor. Aslında, iki proje de aynı şablonları paylaşıyor.
  • [8]'e, projenin mevcut referansları;
  • [9]'te, NuGet aracı kullanılarak Firebird'e ait ADO.NET konektörü eklenmiştir.

[App.config] dosyasında, SQL Sunucu veritabanına ait bilgiler, Firebird veritabanına ait bilgilerle değiştirilir. Bu bilgiler, [RdvMedecins-Firebird-01] projesinin [App.config] dosyasında bulunur:


<!-- veritabanı bağlantı dizesi -->
  <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>
  <!-- fabrika sağlayıcısı -->
  <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 tarafından yönetilen nesneler de değişir. Şu anda elimizde şunlar var:


  <!-- Spring yapılandırması -->
  <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. satır, [RdvMedecins-SqlServer-02] projesinin derlemesine atıfta bulunmaktadır. Derleme artık [RdvMedecins-Firebird-02] şeklindedir.

Bu işlem tamamlandıktan sonra, [DAO] katmanının testini çalıştırmaya hazırız. Öncelikle, [RdvMedecins-Firebird-01] projesindeki [Fill] programını kullanarak veritabanını doldurmamız gerekiyor. Test programı başarılı bir şekilde tamamlandı.

[RdvMedecins-SqlServer-02] projesi için yapıldığı gibi, projenin DLL katmanını oluşturuyoruz ve projeninprojenin tüm DLL dosyalarını, [RdvMedecins-Firebird-02] içinde oluşturulan [lib] klasörüne topluyoruz. Bunlar, takip edecek olan [RdvMedecins-Firebird-03] web projesinin referansları olacaktır.

  

Artık uygulamamızın [ASP.NET] katmanını oluşturmaya hazırız:

[RdvMedecins-SqlServer-03] projesinden başlayacağız. Bu projenin klasörünü [RdvMedecins-Firebird-03] ve [1] olarak çoğaltıyoruz:

  • [2]'e kopyalayacağız; VS 2012 Express for the Web ile [RdvMedecins-Firebird-03] klasöründeki çözümü açacağız;
  • [3]'te hem çözümün adını hem de projenin adını değiştiriyoruz;
  • [4]'te, projenin mevcut referanslarını;
  • [5]'te bunları siliyoruz;
  • [6]'e değiştirip, bunları az önce [RdvMedecins-Firebird-02] projesinin [lib] klasörüne kaydettiğimiz DLL dosyasına yapılan referanslarla değiştiriyoruz.

Geriye sadece [Web.config] dosyasını değiştirmek kalıyor. Mevcut içeriğini, [RdvMedecins-Firebird-02] projesindeki [App.config] dosyasının içeriğiyle değiştiriyoruz. Bu işlem tamamlandıktan sonra web projesini çalıştırıyoruz. Çalışıyor. Web uygulamasını çalıştırmadan önce veritabanını doldurmayı unutmayalım.