Skip to content

7. مطالعه موردی با Firebird 2.1

7.1. نصب ابزارها

ابزارهای قابل نصب به شرح زیر هستند:

  • SGBD: [http://www.firebirdsql.org/en/firebird-2-1-5/];
  • یک ابزار مدیریتی: EMS، SQL مدیر برای InterBase/Firebird Freeware، [http://www.sqlmanager.net/fr/products/ibfb/manager/download].

در مثال‌های زیر، کاربر sysdba با رمز عبور masterkey است.

بیایید Firebird را راه‌اندازی کنیم و سپس ابزار [SQL Manager Lite for Firebird] را که برای مدیریت SGBD استفاده خواهیم کرد.

  • در [1]، ما سرویس SGBD Firebird را از منوی استارت راه‌اندازی می‌کنیم. در اینجا، SGBD به عنوان یک سرویس ویندوز نصب نشده است؛
  • در [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 مربوط به سال ۲۰۱۲ را به این پایگاه داده متصل خواهیم کرد.

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>
  • خط ۳: نام کاربری و رمز عبور، و همچنین مسیر کامل پایگاه داده Firebird؛
  • خطوط ۸–۱۰: DbProviderFactory. خط ۹ به 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

خط ۱ نشان می‌دهد که پایگاه داده در حال استفاده است. من فکر نمی‌کنم این مورد صدق کند و نتوانسته‌ام این مشکل را حل کنم.

مشکلی نیست. ما پایگاه داده [RDVMEDECINS-EF] را به‌صورت دستی با استفاده از ابزار [EMS Manager for Firebird] ایجاد خواهیم کرد. ما هر مرحله را توضیح نمی‌دهیم، بلکه فقط مهم‌ترین مراحل را بیان می‌کنیم.

پایگاه داده Firebird به شرح زیر خواهد بود:

جدول‌ها

  • در [1]، ID یک کلید اصلی با ویژگی Autoincrement است. این کلید به طور خودکار توسط SGBD ایجاد خواهد شد؛

جدول‌های مختلف دارای کلیدهای اصلی و خارجی مشابه جدول‌های مثال‌های قبلی هستند. کلیدهای خارجی دارای ویژگی‌های ON، DELETE و CASCADE هستند.

ژنراتورها

همانند Oracle و PostgreSQL، ما برای اعداد متوالی ژنراتورهایی ایجاد کرده‌ایم. تعداد آن‌ها پنج عدد است: [1].

  • [CLIENTS_ID_GEN] برای تولید کلید اصلی برای جدول [CLIENTS] استفاده خواهد شد؛
  • [MEDECINS_ID_GEN] برای تولید کلید اصلی جدول [MEDECINS] استفاده خواهد شد؛
  • [CRENEAUX_ID_GEN] برای تولید کلید اصلی جدول [CRENEAUX] استفاده خواهد شد؛
  • [RVS_ID_GEN] برای تولید کلید اصلی جدول [RVS] استفاده خواهد شد؛
  • [VERSIONS_GEN] برای تولید مقادیر ستون‌های [VERSIONING] در تمام جداول استفاده خواهد شد.

تریگرها

یک تله (Trigger) روندی است که توسط SGBD قبل یا بعد از یک رویداد (درج، به‌روزرسانی، حذف) در یک جدول اجرا می‌شود. ما ۸ تله داریم: [1]:

بیایید نگاهی به کد تریگر DDL بیندازیم که ستون [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^
  • خط ۲: قبل از هر درج در جدول [CLIENTS];
  • خطوط ۶–۷: اگر ستون 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^
  • خطوط ۱–۳: قبل از هر عملیات INSERT یا UPDATE روی جدول [CLIENTS
  • خط ۶: ستون ["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

بیایید به مطالعه موردی خود که در پاراگراف ۲ توصیف شده است بازگردیم.

ما با ساخت لایه دسترسی به داده [DAO] شروع خواهیم کرد. برای این کار، پروژهٔ کنسول VS 2012 [RdvMedecins-SqlServer-02] را در [RdvMedecins-Firebird-02] [1] کپی می‌کنیم:

  • به [2]، و پروژه [RdvMedecins-SqlServer-02] را حذف کنید؛
  • در [3]، یک پروژه موجود به راه‌حل اضافه می‌شود. این پروژه از پوشه [RdvMedecins-Firebird-02] که به تازگی ایجاد شده است، گرفته می‌شود؛
  • در [4]، پروژه جدید همان نام پروژه‌ای را دارد که حذف شده بود. ما آن را نام‌گذاری مجدد خواهیم کرد؛
  • در [5]، نام پروژه را تغییر داده‌ایم؛
  • در [6]، ما در حال تغییر برخی از ویژگی‌های آن هستیم، مانند نام assembly در اینجا؛
  • در [7]، پوشه [Models] حذف شده و با پوشه [Models] از پروژه [RdvMedecins-Firebird-01] جایگزین می‌شود. این به این دلیل است که این دو پروژه از همان قالب‌ها استفاده می‌کنند.
  • در [8]، پروژه‌های جاری ارجاع می‌دهند؛
  • در [9]، کانکتور Firebird ADO.NET با استفاده از ابزار NuGet اضافه شده است.

در فایل [App.config]، اطلاعات پایگاه داده سرور SQL با اطلاعات پایگاه داده 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>

خط ۷ به اسمبلی پروژه [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 for the Web، راه‌حل را در پوشه [RdvMedecins-Firebird-03] باز می‌کنیم؛
  • در [3]، ما هم نام راه‌حل و هم نام پروژه را تغییر می‌دهیم؛
  • در [4]، پروژه‌های مرجع فعلی؛
  • در [5]، آن‌ها را حذف می‌کنیم؛
  • آنها را با ارجاع به فایل‌های DLL که به تازگی در پوشه‌ای به نام [lib] در پروژه [RdvMedecins-Firebird-02] ذخیره کرده‌ایم، جایگزین می‌کنیم.

تنها کاری که باقی مانده، اصلاح فایل [Web.config] است. ما محتوای فعلی آن را با محتوای فایل [App.config] از پروژه [RdvMedecins-Firebird-02] جایگزین می‌کنیم. پس از انجام این کار، پروژه وب را اجرا می‌کنیم. کار می‌کند. قبل از اجرای وب‌اپلیکیشن، فراموش نکنید که پایگاه داده را پر کنید.