Skip to content

7. دسترسی به پایگاه‌های داده

7.1. اطلاعات عمومی

بانک‌های اطلاعاتی متعددی برای پلتفرم‌های ویندوز در دسترس هستند. برای دسترسی به آن‌ها، برنامه‌ها از برنامه‌هایی به نام درایور استفاده می‌کنند.

در نمودار بالا، درایور دو رابط دارد:

  • رابط I1 که به برنامه ارائه می‌شود
  • رابط I2 به پایگاه داده

برای اطمینان از اینکه یک برنامه نوشته شده برای پایگاه داده B1 هنگام مهاجرت به یک پایگاه داده متفاوت B2 نیازی به بازنویسی نداشته باشد، کارهای استانداردسازی روی رابط I1 انجام شده است. اگر از پایگاه‌های داده‌ای که از درایورهای «استانداردسازی‌شده» استفاده می‌کنند بهره گرفته شود، پایگاه داده B1 به همراه درایور P1 ارائه خواهد شد، پایگاه داده B2 با درایور P2، و رابط کاربری I1 برای هر دوی این درایورها یکسان خواهد بود. در نتیجه، نیازی به بازنویسی برنامه نخواهد بود. برای مثال، امکان مهاجرت یک پایگاه داده ACCESS به یک پایگاه داده MySQL بدون تغییر در برنامه وجود خواهد داشت.

دو نوع درایور استاندارد وجود دارد:

  • راننده‌های ODBC (اتصال باز DataBase)
  • راننده‌های OLE و DB (پیوند و جاسازی اشیاء DataBase)

راننده‌های ODBC دسترسی به پایگاه‌های داده را فراهم می‌کنند. منابع داده برای راننده‌های OLE و DB متنوع‌تر هستند: پایگاه‌های داده، سیستم‌های ایمیل، دایرکتوری‌ها و غیره. هیچ محدودیتی وجود ندارد. هر منبع داده‌ای می‌تواند موضوع یک درایور OLE یا DB باشد، اگر فروشنده نرم‌افزار چنین تصمیم بگیرد. مزایای آن، البته، قابل توجه است: شما دسترسی یکنواختی به طیف گسترده‌ای از داده‌ها دارید.

پلتفرم .NET با دو نوع کلاس دسترسی به داده‌ها عرضه می‌شود:

  1. کلاس‌های SQL و Server.NET
  2. کلاس‌های OLE و Db.NET

مجموعه اول کلاس‌ها دسترسی مستقیم به سرور Microsoft SGBD SQL را بدون نیاز به درایور واسط فراهم می‌کند. مجموعه دوم دسترسی به منابع داده OLE DB را امکان‌پذیر می‌سازد.

Image

پلتفرم .NET (مه ۲۰۰۲) با سه درایور عرضه می‌شود: OLE، DB و SQL، به ترتیب برای سرور، اوراکل و مایکروسافت جت (اکسل). اگر بخواهید با پایگاه‌داده‌ای کار کنید که درایور ODBC دارد اما درایور OLE یا DB را ندارد، نمی‌توانید این کار را انجام دهید. بنابراین، شما نمی‌توانید با SGBD یا MySQL کار کنید، که (تا مه ۲۰۰۲) درایوری برای OLE یا DB ارائه نمی‌دهند. با این حال، مجموعه‌ای از کلاس‌ها وجود دارد که امکان دسترسی به منابع داده ODBC را فراهم می‌کنند: کلاس‌های odbc.net. این کلاس‌ها به صورت استاندارد با SDK ارائه نمی‌شوند و باید از وب‌سایت مایکروسافت دانلود شوند. در مثال‌های بعدی، ما عمدتاً از این کلاس‌های ODBC استفاده خواهیم کرد، زیرا اکثر پایگاه‌های داده‌ای که روی ویندوز اجرا می‌شوند، دارای چنین درایوری هستند. در اینجا، به‌عنوان مثال، فهرستی از درایورهای ODBC نصب‌شده روی یک سیستم ویندوز ۲۰۰۰ آورده شده است (منوی استارت/تنظیمات/پنل کنترل/ابزارهای مدیریتی):

Image

آیکون منبع داده ODBC را انتخاب کنید:

Image

7.2. دو روش استفاده از یک منبع داده

پلتفرم .NET امکان استفاده از یک منبع داده را به دو روش مختلف فراهم می‌کند:

  1. حالت متصل
  2. حالت آفلاین

در حالت متصل، برنامه

  1. یک اتصال به منبع داده برقرار می‌کند
  2. در حالت خواندن/نوشتن با منبع داده کار می‌کند
  3. ارتباط را قطع می‌کند

در حالت آفلاین، برنامه

  1. یک اتصال به منبع داده باز می‌کند
  2. یک نسخهٔ در حافظه‌ای از تمام یا بخشی از داده‌ها را از منبع بازیابی می‌کند
  3. اتصال را قطع می‌کند
  4. با کپی موجود در حافظهٔ داده‌ها کار می‌کند، از آن می‌خواند و در آن می‌نویسد
  5. پس از اتمام کار، اتصال را باز می‌کند، داده‌های اصلاح‌شده را برای به‌روزرسانی به منبع داده ارسال می‌کند و اتصال را می‌بندد

در هر دو حالت، این فرآیند پردازش و به‌روزرسانی داده‌ها است که زمان‌بر است. بیایید تصور کنیم که این به‌روزرسانی‌ها توسط کاربری که داده‌ها را وارد می‌کند انجام می‌شود؛ این فرآیند می‌تواند ده‌ها دقیقه طول بکشد. در تمام این مدت، در حالت متصل، اتصال به پایگاه داده حفظ می‌شود و تغییرات بلافاصله منعکس می‌شوند. در حالت آفلاین، در حین به‌روزرسانی داده‌ها، هیچ اتصالی به پایگاه داده وجود ندارد. تغییرات صرفاً روی کپی موجود در حافظه انجام می‌شوند. این تغییرات پس از اتمام کار، یکجا در منبع داده منعکس می‌شوند.

مزایا و معایب این دو روش چیست؟

  • یک اتصال منابع زیادی از سیستم را مصرف می‌کند. اگر اتصالات همزمان زیادی وجود داشته باشد، حالت آفلاین به کوتاه کردن مدت زمان آن‌ها کمک می‌کند. این موضوع در مورد برنامه‌های وب با هزاران کاربر صادق است.
  • نقطه‌ضعف حالت آفلاین، مدیریت پیچیدهٔ به‌روزرسانی‌های همزمان است. کاربر U1 در زمان T1 داده‌ها را بازیابی می‌کند و شروع به اصلاح آن‌ها می‌کند. در زمان T2، کاربر U2 نیز به منبع داده دسترسی پیدا کرده و همان داده‌ها را بازیابی می‌کند. در همین حال، کاربر U1 برخی از داده‌ها را تغییر داده اما هنوز آن را به منبع داده بازنفرستاده است. بنابراین U2 در حال کار با داده‌هایی است که برخی از آن‌ها نادرست هستند. کلاس‌های NET راه‌حل‌هایی برای مدیریت این مشکل ارائه می‌دهند، اما حل آن ساده نیست.
  • در حالت متصل، به‌روزرسانی همزمان داده‌ها توسط چندین کاربر معمولاً مشکلی ایجاد نمی‌کند. از آنجایی که اتصال به پایگاه داده حفظ می‌شود، خود پایگاه داده است که این به‌روزرسانی‌های همزمان را مدیریت می‌کند. بنابراین، اوراکل به محض اینکه کاربر ردیفی را تغییر دهد، آن را قفل می‌کند. این ردیف قفل‌شده باقی می‌ماند — و در نتیجه برای سایر کاربران در دسترس نخواهد بود — تا زمانی که کاربری که آن را تغییر داده، تغییر را commit کند یا آن را roll back نماید.
  • اگر نیاز باشد داده‌ها از طریق شبکه منتقل شوند، باید حالت آفلاین انتخاب شود. این حالت، نمایی از داده‌ها را در ابجکتی به نام مجموعه داده (dataset) فراهم می‌کند که خود به عنوان یک پایگاه داده عمل می‌کند. این ابجکت را می‌توان از طریق شبکه بین ماشین‌ها منتقل کرد.

ابتدا حالت متصل را بررسی خواهیم کرد.

7.3. دسترسی به داده‌ها در حالت متصل

7.3.1. پایگاه‌های داده در مثال

ما در حال بررسی یک پایگاه داده به نام ACCESS هستیم که به عنوان articles.mdb شناخته می‌شود و تنها شامل یک جدول به نام ARTICLES با ساختار زیر است:

نام
نوع
کد
کد آیتم ۴ کاراکتری
name
نام آن (رشتهٔ کاراکتری)
قیمت
قیمت آن (واقعی)
stock_actuel
موجودی فعلی آن (اعداد صحیح)
stock_minimum
حداقل سطح موجودی (صحيح) که کالا باید پس از کاهش از آن دوباره موجودی شود

محتویات اولیه آن به شرح زیر است:

Image

ما از این مجموعه داده هم در یک ODBC آزمایشی ویک درایور OLE DB برای نشان دادن شباهت بین دو رویکرد و به این دلیل که هر دو نوع درایور برای ACCESS در دسترس ما هستند.

ما همچنین از پایگاه داده MySQL DBARTICLES که حاوی همان جدول واحد ARTICLES است، استفاده خواهیم کرد، همان محتوا را از طریق درایور ODBC در دسترس قرار می‌دهد، تا نشان دهد که برنامه‌ای که برای استفاده از پایگاه داده ACCESS نوشته شده است، برای استفاده از پایگاه داده MySQL نیازی به تغییر ندارد. پایگاه داده DBARTICLES برای کاربری به نام admarticles با رمز عبور mdparticles قابل دسترسی است. اسکرین‌شات زیر محتویات پایگاه داده MySQL را نشان می‌دهد:

C:\mysql\bin>mysql --database=dbarticles --user=admarticles --password=mdparticles
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3 to server version: 3.23.49-max-debug

Type 'help' for help.


mysql> show tables;
+----------------------+
| Tables_in_dbarticles |
+----------------------+
| articles             |
+----------------------+
1 row in set (0.01 sec)

mysql> select * from articles;
+------+--------------------------------+------+--------------+---------------+
| code | nom                            | prix | stock_actuel | stock_minimum |
+------+--------------------------------+------+--------------+---------------+
| a300 | vÚlo                           | 2500 |           10 |             5 |
| b300 | pompe                          |   56 |           62 |            45 |
| c300 | arc                            | 3500 |           10 |            20 |
| d300 | flÞches - lot de 6             |  780 |           12 |            20 |
| e300 | combinaison de plongÚe         | 2800 |           34 |             7 |
| f300 | bouteilles d'oxygÞne           |  800 |           10 |             5 |
+------+--------------------------------+------+--------------+---------------+
6 rows in set (0.02 sec)

mysql> describe articles;
+---------------+-------------+------+-----+---------+-------+
| Field         | Type        | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| code          | text        | YES  |     | NULL    |       |
| nom           | text        | YES  |     | NULL    |       |
| prix          | double      | YES  |     | NULL    |       |
| stock_actuel  | smallint(6) | YES  |     | NULL    |       |
| stock_minimum | smallint(6) | YES  |     | NULL    |       |
+---------------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> exit
Bye

برای تعریف پایگاه داده ACCESS به‌عنوان منبع داده ODBC، مراحل زیر را انجام دهید:

  • مدیر منبع داده ODBC را همان‌طور که در بالا نشان داده شده باز کنید و برگه User DSN را انتخاب کنید (DSN=نام منبع داده)

Image

  • با استفاده از دکمه Add یک منبع اضافه کنید، مشخص کنید که این منبع از طریق یک درایور Access قابل دسترسی است و Terminer را انجام دهید:

Image

  • منبع داده articles-access را نام ببرید، توضیح دلخواه خود را وارد کنید و با استفاده از دکمه Sélectionner فایل .mdb را از پایگاه داده انتخاب کنید. کار را با OK به پایان برسانید.

Image

سپس منبع داده جدید در لیست منابع داده کاربر ظاهر خواهد شد: DSN:

Image

برای تعریف پایگاه داده MySQL DBARTICLES به عنوان منبع داده ODBC، مراحل زیر را دنبال کنید:

  • مدیر منبع داده ODBC را همان‌طور که در بالا نشان داده شده باز کنید و زبانه User (DSN) را انتخاب کنید. با استفاده از Add یک منبع داده جدید اضافه کنید و درایور ODBC را از MySQL انتخاب کنید.

Image

  • Terminer را اجرا کنید. سپس صفحه‌ای برای پیکربندی منبع MySQL ظاهر می‌شود:

54321

Image

  • در (۱)، برای منبع داده خود ODBC نامی وارد کنید.
  • در (۲)، ماشینی را که سرور روی آن قرار دارد مشخص کنید: MySQL. در اینجا localhost را وارد می‌کنیم تا نشان دهیم که روی همان ماشینی قرار دارد که برنامه ما روی آن است. اگر سرور MySQL روی یک ماشین راه دور M قرار داشت، نام آن را اینجا وارد می‌کردیم و برنامه ما سپس بدون هیچ تغییری با یک پایگاه داده راه دور اجرا می‌شد.
  • در (۳)، نام پایگاه داده را وارد کنید. در اینجا، DBARTICLES نام دارد.
  • در (۴)، نام کاربری admarticles و در (۵) رمز عبور mdparticles را وارد کنید.

7.3.2. استفاده از درایور ODBC

در یک برنامه کاربردی که از پایگاه داده در حالت متصل استفاده می‌کند، مراحل زیر معمولاً درگیر هستند:

  1. اتصال به پایگاه داده
  2. ارسال پرس‌وجوها SQL به پایگاه داده
  3. دریافت و پردازش نتایج این پرس‌وجوها
  4. بستن اتصال

مراحل ۲ و ۳ به طور مکرر انجام می‌شوند و اتصال تنها زمانی قطع می‌شود که از پایگاه داده به طور کامل استفاده شده باشد. این الگوی نسبتاً استانداردی است که اگر به صورت تعاملی از پایگاه داده استفاده کرده باشید، ممکن است با آن آشنا باشید. این مراحل صرف‌نظر از اینکه به پایگاه داده از طریق یک درایور ODBC یا یک درایور OLE یا DB دسترسی پیدا شود، یکسان هستند. در زیر مثالی با استفاده از کلاس‌های NET برای مدیریت منابع داده ODBC آورده شده است. این برنامه liste نام دارد و به‌عنوان پارامتر نام DSN یک منبع داده ODBC را که شامل یک جدول ARTICLES است، می‌پذیرد. سپس محتویات این جدول را نمایش می‌دهد:

dos>liste
syntaxe : pg dsnArticles

dos>liste articles-access

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5

dos>liste mysql-artices
Erreur d'exploitation de la base de données (ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified)

dos>liste mysql-articles

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5

از نتایج بالا می‌توان دید که برنامه محتویات هر دو پایگاه داده ACCESS و MySQL را فهرست کرده است. اکنون بیایید کد این برنامه را بررسی کنیم:


' گزینه‌ها
Option Explicit On 
Option Strict On

' فضاهای نام
Imports System
Imports System.Data
Imports Microsoft.Data.Odbc
Imports Microsoft.VisualBasic

Module db1
    Sub main(ByVal args As String())
        ' برنامه کنسول
        'محتویات جدول ARTICLES را در پایگاه داده DSN نمایش می‌دهد 
        ' که نام آن به‌عنوان پارامتر ارسال می‌شود
        Const syntaxe As String = "syntaxe : pg dsnArticles"
        Const tabArticles As String = "articles"        ' la table des articles

        'بررسی پارامتر
        'آیا یک پارامتر وجود دارد
        If args.Length <> 1 Then
            ' پیام خطا
            Console.Error.WriteLine(syntaxe)
            'پایان
            Environment.Exit(1)
        End If

        ' بازیابی پارامتر
        Dim dsnArticles As String = args(0)                ' la base DSN
        ' آماده‌سازی اتصال پایگاه داده
        Dim articlesConn As OdbcConnection = Nothing        ' la connexion
        Dim myReader As OdbcDataReader = Nothing            ' le lecteur de données

        ' در حال تلاش برای دسترسی به پایگاه داده
        Try
            ' رشته اتصال پایگاه داده
            Dim connectString As String = "DSN=" + dsnArticles + ";"
            articlesConn = New OdbcConnection(connectString)
            articlesConn.Open()

            ' اجرای یک فرمان SQL
            Dim sqlText As String = "select * from " + tabArticles
            Dim myOdbcCommand As New OdbcCommand(sqlText)
            myOdbcCommand.Connection = articlesConn
            myReader = myOdbcCommand.ExecuteReader()

            ' پردازش جدول بازیابی‌شده
            'نمایش ستون‌ها
            Dim ligne As String = ""
            Dim i As Integer
            For i = 0 To (myReader.FieldCount - 1) - 1
                ligne += myReader.GetName(i) + ","
            Next i
            ligne += myReader.GetName(i)
            Console.Out.WriteLine((ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf + ligne + ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf))

            'نمایش داده‌ها
            While myReader.Read()
                'پردازش سطر جاری
                ligne = ""
                For i = 0 To myReader.FieldCount - 1
                    ligne += myReader(i).ToString + " "
                Next i
                Console.WriteLine(ligne)
            End While
        Catch ex As Exception
            Console.Error.WriteLine(("Erreur d'exploitation de la base de données " + ex.Message + ")"))
            Environment.Exit(2)
        Finally
            'بستن خواننده
            myReader.Close()
            ' بستن اتصال
            articlesConn.Close()
        End Try
    End Sub
End Module

کلاس‌های مدیریت منبع ODBC در فضای نام Microsoft.Data.Odbc قرار دارند، که بنابراین باید وارد شوند. علاوه بر این، تعدادی کلاس در فضای نام System.Data قرار دارند.


Imports System.Data
Imports Microsoft.Data.Odbc

فضای نام‌های مورد استفاده توسط برنامه در اسمبلی‌های مختلف قرار دارند. برنامه با استفاده از دستور زیر کامپایل می‌شود:

dos>vbc /r:microsoft.data.odbc.dll /r:microsoft.visualbasic.dll /r:system.dll /r:system.data.dll db1.vb

7.3.2.1. مرحله اتصال

یک اتصال ODBC از کلاس OdbcConnection استفاده می‌کند. سازنده این کلاس متنی به نام رشته اتصال را به‌عنوان پارامتر می‌پذیرد. این یک رشته از کاراکترها است که تمام پارامترهای لازم برای برقراری ارتباط با پایگاه داده را تعریف می‌کند. ممکن است تعداد زیادی از این پارامترها وجود داشته باشد، بنابراین این رشته می‌تواند پیچیده باشد. این رشته به شکل "param1=valeur1;param2=valeur2;...;paramj=valeurj;" است. در اینجا برخی از پارامترهای ممکن paramj آورده شده است:

uid
نام کاربری کاربری که به پایگاه داده دسترسی خواهد داشت
password
رمز عبور آن کاربر
dsn
نام پایگاه داده (DSN) در صورت وجود
data source
نام پایگاه دادهٔ دسترسی‌یافته
...
 

اگر یک منبع داده با استفاده از مدیر منبع داده ODBC به عنوان منبع داده ODBC تعریف شده باشد، این پارامترها قبلاً مشخص و ذخیره شده‌اند. تمام کاری که باید انجام دهید این است که پارامتر DSN را که نام DSN منبع داده را مشخص می‌کند، ارسال کنید. این کاری است که در اینجا انجام می‌شود:


         ' آماده‌سازی اتصال پایگاه داده
        Dim articlesConn As OdbcConnection = Nothing        ' la connexion
        Dim myReader As OdbcDataReader = Nothing        ' le lecteur de données
        Try
             ' تلاش برای دسترسی به پایگاه داده
             ' رشته اتصال پایگاه داده
            Dim connectString As String = "DSN=" + dsnArticles + ";"
            articlesConn = New OdbcConnection(connectString)
            articlesConn.Open()

پس از ایجاد شیء OdbcConnection، اتصال با استفاده از متد Open باز می‌شود. این تلاش برای اتصال، درست مانند هر عملیات دیگری روی پایگاه داده، ممکن است ناموفق باشد. به همین دلیل است که تمام کد مربوط به دسترسی به پایگاه داده در یک try-catch قرار دارد. پس از برقراری اتصال، می‌توان پرس‌وجوهای SQL را به پایگاه داده ارسال کرد.

7.3.2.2. ارسال پرس‌وجوهای SQL

برای اجرای پرس‌وجوهای SQL، به یک شیء Command نیاز داریم؛ دقیق‌تر بگوییم، یک شیء OdbcCommand، زیرا ما از یک منبع داده ODBC استفاده می‌کنیم. کلاس OdbcCommand دارای چندین سازنده است:

  • OdbcCommand(): یک شیء خالی Command ایجاد می‌کند. برای استفاده از آن، در مرحله بعد باید ویژگی‌های مختلفی مشخص شوند:
    • CommandText: متن پرس‌وجوی SQL که باید اجرا شود
    • Connection: شی OdbcConnection که نمایانگر اتصال به پایگاه داده‌ای است که پرس‌وجو روی آن اجرا خواهد شد
    • CommandType: نوع پرس‌وجوی SQL. سه مقدار ممکن وجود دارد
  1. CommandType.Text: ویژگی CommandText حاوی متن یک پرس‌وجوی SQL است (ارزش پیش‌فرض)
  2. CommandType.StoredProcedure: ویژگی CommandText شامل نام یک رویهٔ ذخیره‌شده در پایگاه داده است
  3. CommandType.TableDirect: ویژگی CommandText حاوی نام یک جدول T است. معادل `SELECT * FROM T`. فقط برای درایورهای OLE و DB وجود دارد.
  • OdbcCommand(string sqlText): پارامتر sqlText به ویژگی CommandText اختصاص داده می‌شود. این متن پرس‌وجوی SQL است که باید اجرا شود. اتصال باید در ویژگی Connection مشخص شود.
  • OdbcCommand(string sqlText, OdbcConnection connection): پارامتر sqlText به خصوصیت CommandText و پارامتر connexion به خصوصیت Connection اختصاص داده می‌شود.

دو روش برای اجرای پرس‌وجوی SQL وجود دارد:

  • OdbcdataReader ExecuteReader(): پرس‌وجوی SELECT را از CommandText به اتصال Connection ارسال می‌کند و یک شیء OdbcDataReader ایجاد می‌کند که اجازه می‌دهددسترسی به تمام سطرها در جدول نتایج select را فراهم می‌کند
  • int ExecuteNOnQuery(): درخواست به‌روزرسانی را ارسال می‌کند (INSERT, UPDATE, DELETE) از CommandText به اتصال Connection ارسال می‌شود و تعداد ردیف‌های تحت تأثیر این به‌روزرسانی را بازمی‌گرداند.

در مثال ما، پس از باز کردن اتصال به پایگاه داده، یک پرس‌وجو SQL SELECT را برای بازیابی محتویات جدول ARTICLES اجرا می‌کنیم:


             ' اجرای یک دستور SQL
            Dim sqlText As String = "select * from " + tabArticles
            Dim myOdbcCommand As New OdbcCommand(sqlText)
            myOdbcCommand.Connection = articlesConn
            myReader = myOdbcCommand.ExecuteReader()

یک پرس‌وجو معمولاً از نوع زیر است:


    select col1, col2,... from table1, table2,...
    where condition
    order by expression
    ...

فقط کلمات کلیدی در خط اول اجباری هستند؛ سایر کلمات اختیاری‌اند. کلمات کلیدی دیگری نیز وجود دارند که در اینجا نشان داده نشده‌اند.

  1. پیوند با تمام جداول فهرست‌شده پس از کلمهٔ کلیدی «from» انجام می‌شود
  2. فقط ستون‌هایی که پس از کلمهٔ کلیدی «select» می‌آیند، نگه‌داری می‌شوند
  3. فقط سطرهایی که شرط مشخص‌شده توسط کلیدواژه «where» را برآورده می‌کنند، نگه‌داری می‌شوند
  4. رده‌های حاصل، بر اساس عبارت در کلیدواژه «ORDER BY» مرتب شده و نتیجه پرس‌وجو را تشکیل می‌دهند.

نتیجه یک پرس‌وجوی select یک جدول است. اگر جدول قبلی ARTICLES را در نظر بگیریم و بخواهیم نام اقلامی را که موجودی فعلی‌شان کمتر از آستانهٔ حداقل است، به دست آوریم، خواهیم نوشت:


    select nom from articles where stock_actuel<stock_minimum

اگر بخواهید آن‌ها را به ترتیب الفبا بر اساس نام فهرست کنید، وارد می‌کنید:


    select nom from articles where stock_actuel<stock_minimum order by nom

7.3.2.3. تحلیل نتیجه یک پرس‌وجوی SELECT

نتیجه یک پرس‌وجوی SELECT در حالت آفلاین یک شیء DataReader است؛ در اینجا، یک شیء OdbcDataReader. این شیء به شما امکان می‌دهد تا تمام سطرهای نتیجه را به صورت متوالی بازیابی کرده و اطلاعاتی در مورد ستون‌های این نتایج به دست آورید. بیایید برخی از ویژگی‌ها و متدهای این کلاس را بررسی کنیم:

FieldCount
تعداد ستون‌ها در جدول
Item
Item(i) نمایانگر شماره ستون i از سطر جاری در نتیجه است
XXX GetXXX(i)
مقدار ستون شماره i در ردیف جاری، که به نوع XXX (Int16, Int32, Int64, Double, String, Boolean, ...) بازگردانده می‌شود
string GetName(i)
نام ستون شماره i
Close()
شیء OdbcdataReader را می‌بندد و منابع مرتبط را آزاد می‌کند
bool Read()
یک سطر به جلو در جدول نتایج حرکت می‌کند. اگر این امکان وجود نداشته باشد، مقدار false را برمی‌گرداند. سطر جدید به سطر جاری خواننده تبدیل می‌شود.

پردازش نتیجه یک select معمولاً یک فرآیند ترتیبی است که مشابه فایل‌های متنی است: فقط می‌توان در جدول به جلو حرکت کرد، نه به عقب:


While myReader.Read()
    'یک سطر بازیابی شده است – در حال پردازش آن
    ....
     ' ردیف بعدی
end while

این توضیحات برای درک کد زیر از مثال ما کافی است:


            ' پردازش جدول بازیابی‌شده
            'نمایش ستونی
            Dim ligne As String = ""
            Dim i As Integer
            For i = 0 To (myReader.FieldCount - 1) - 1
                ligne += myReader.GetName(i) + ","
            Next i
            ligne += myReader.GetName(i)
            Console.Out.WriteLine((ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf + ligne + ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf))

            'نمایش داده
            While myReader.Read()
                'پردازش سطر جاری
                ligne = ""
                For i = 0 To myReader.FieldCount - 1
                    ligne += myReader(i).ToString + " "
                Next i
                Console.WriteLine(ligne)
            End While

تنها دشواری در دستوری نهفته است که در آن مقادیر ستون‌های مختلف ردیف جاری با هم الحاق می‌شوند:


                For i = 0 To myReader.FieldCount - 1
                    ligne += myReader(i).ToString + " "
                Next i

علامت line+=myReader(i).ToString به صورت line+=myReader.Item(i).ToString ترجمه می‌شود.ToString() که در آن Item(i) مقدار ستون i در سطر جاری است.

7.3.2.4. رهاسازی منبع

کلاس‌های OdbcReader و OdbcConnection هر دو دارای متد Close() هستند که منابع مرتبط با اشیاء بسته‌شده را آزاد می‌کند.

                 'بستن خواننده
                myReader.Close()
                 ' بستن اتصال
                articlesConn.Close()

7.3.3. با استفاده از درایور OLE DB

ما از همان مثال استفاده خواهیم کرد، این بار با یک پایگاه داده که از طریق درایور OLE DB دسترسی پیدا می‌کند. پلتفرم .NET چنین درایوری را برای پایگاه‌های داده ACCESS فراهم می‌کند. بنابراین ما همان پایگاه داده articles.mdb را مانند قبل استفاده خواهیم کرد. هدف ما در اینجا نشان دادن این است که در حالی که کلاس‌ها ممکن است تغییر کنند، مفاهیم یکسان باقی می‌مانند:

  • ارتباط توسط یک شیء OleDbConnection نشان داده می‌شود
  • یک پرس‌وجو SQL با استفاده از یک شیء OleDbCommand صادر می‌شود
  • اگر این پرس‌وجو یک عبارت SELECT باشد، یک شیء OleDbDataReader برای دسترسی به سطرهای جدول نتایج بازگردانده خواهد شد

این کلاس‌ها در فضای نام System.Data.OleDb قرار دارند. برنامه قبلی را می‌توان به‌سادگی برای کار با پایگاه داده OLE یا DB تطبیق داد:

  • در سراسر کد، OdbcXX را با OleDbXX جایگزین کنید
  • رشته اتصال را تغییر دهید. برای یک پایگاه داده با نام ACCESS بدون نام کاربری یا رمز عبور، رشته اتصال به صورت Provider=Microsoft.JET.OLEDB.4.0;Data Source=[fichier.mdb] است. بخش قابل پیکربندی این رشته، نام فایل ACCESS است که باید استفاده شود. ما برنامه خود را طوری تغییر خواهیم داد که نام این فایل را به‌عنوان یک پارامتر بپذیرد.
  • فضای نامی که باید وارد شود اکنون System.Data.OleDb است.

برنامه ما به شکل زیر درمی‌آید:


' گزینه‌ها
Option Explicit On 
Option Strict On

' فضاهای نام
Imports System
Imports System.Data
Imports Microsoft.Data.Odbc
Imports Microsoft.VisualBasic
Imports System.Data.OleDb

Module db2
    Public Sub Main(ByVal args() As String)

        ' برنامه کنسول
        'محتویات یک جدول ARRTICLES را در یک پایگاه داده DSN نمایش می‌دهد 
        ' که نام آن به‌عنوان پارامتر ارسال می‌شود
        Const syntaxe As String = "syntaxe : pg base_access_articles"
        Const tabArticles As String = "articles"        ' la table des articles

        'اعتبارسنجی پارامتر
        'آیا یک پارامتر وجود دارد
        If args.Length <> 1 Then
            ' پیام خطا
            Console.Error.WriteLine(syntaxe)
            'پایان
            Environment.Exit(1)
        End If

        ' بازیابی پارامتر
        Dim dbArticles As String = args(0)        ' la base de données

        ' آماده‌سازی اتصال پایگاه داده
        Dim articlesConn As OleDbConnection = Nothing        ' la connexion
        Dim myReader As OleDbDataReader = Nothing        ' le lecteur de données

        ' در حال تلاش برای دسترسی به پایگاه داده

        Try
            ' رشته اتصال پایگاه داده
            Dim connectString As String = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + dbArticles + ";"
            articlesConn = New OleDbConnection(connectString)
            articlesConn.Open()

            ' اجرای یک دستور SQL
            Dim sqlText As String = "select * from " + tabArticles
            Dim myOleDbCommand As New OleDbCommand(sqlText)
            myOleDbCommand.Connection = articlesConn
            myReader = myOleDbCommand.ExecuteReader()

            ' پردازش جدول بازیابی‌شده
            'نمایش ستون‌ها
            Dim ligne As String = ""
            Dim i As Integer
            For i = 0 To (myReader.FieldCount - 1) - 1
                ligne += myReader.GetName(i) + ","
            Next i
            ligne += myReader.GetName(i)
            Console.Out.WriteLine((ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf + ligne + ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf))
            'نمایش داده‌ها
            While myReader.Read()
                'پردازش سطر جاری
                ligne = ""
                For i = 0 To myReader.FieldCount - 1
                    ligne += myReader(i).ToString + " "
                Next i
                Console.WriteLine(ligne)
            End While
        Catch ex As Exception
            Console.Error.WriteLine(("Erreur d'exploitation de la base de données (" + ex.Message + ")"))
            Environment.Exit(2)
        Finally
            'بستن خواننده
                myReader.Close()
                ' بستن اتصال
                articlesConn.Close()
        End Try
        'پایان
        Environment.Exit(0)
    End Sub
End Module

نتایج به‌دست‌آمده:

dos>vbc liste.vb

E:\data\serge\MSNET\vb.net\adonet\6>dir
07/05/2002  15:09                2 325 liste.CS
07/05/2002  15:09                4 608 liste.exe
20/08/2001  11:54               86 016 ARTICLES.MDB

dos>liste articles.mdb

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5

7.3.4. به‌روزرسانی یک جدول

مثال‌های قبلی صرفاً محتویات یک جدول را فهرست می‌کردند. ما در حال اصلاح برنامه مدیریت پایگاه داده آیتم خود هستیم تا بتواند پایگاه داده را ویرایش کند. این برنامه sql نام دارد. ما نام پایگاه داده آیتم DSN که باید مدیریت شود را به عنوان یک پارامتر ارسال می‌کنیم. کاربر دستورات SQL را مستقیماً از روی صفحه‌کلید وارد می‌کند که برنامه آن‌ها را اجرا می‌کند، همان‌طور که در نتایج زیر که از پایگاه داده مقاله MySQL به دست آمده، نشان داده شده است:

dos>vbc /r:microsoft.data.odbc.dll sql.vb

dos>sql mysql-articles

Requête SQL (fin pour arrêter) : select * from articles

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5

Requête SQL (fin pour arrêter) : select * from articles where stock_actuel<stock_minimum

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20

Requête SQL (fin pour arrêter) : insert into articles values ("1","1",1,1,1)
Il y a eu 1 ligne(s) modifiée(s)

Requête SQL (fin pour arrêter) : select * from articles

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5
1 1 1 1 1

Requête SQL (fin pour arrêter) : update articles set nom="2" where nom="1"
Il y a eu 1 ligne(s) modifiée(s)

Requête SQL (fin pour arrêter) : select * from articles

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5
1 2 1 1 1

Requête SQL (fin pour arrêter) : delete from articles where code="1"
Il y a eu 1 ligne(s) modifiée(s)

Requête SQL (fin pour arrêter) : select * from articles

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

a300 vélo                           2500 10 5
b300 pompe                          56 62 45
c300 arc                            3500 10 20
d300 flèches - lot de 6             780 12 20
e300 combinaison de plongée         2800 34 7
f300 bouteilles d'oxygène           800 10 5

Requête SQL (fin pour arrêter) : select * from articles order by nom asc

----------------------------------------
code,nom,prix,stock_actuel,stock_minimum
----------------------------------------

c300 arc                            3500 10 20
f300 bouteilles d'oxygène           800 10 5
e300 combinaison de plongée         2800 34 7
d300 flèches - lot de 6             780 12 20
b300 pompe                          56 62 45
a300 vélo                           2500 10 5

Requête SQL (fin pour arrêter) : fin

برنامه به شرح زیر است:


' گزینه‌ها
Option Explicit On 
Option Strict On

' فضاهای نام
Imports System
Imports System.Data
Imports Microsoft.Data.Odbc
Imports System.Data.OleDb
Imports System.Text.RegularExpressions
Imports System.Collections
Imports Microsoft.VisualBasic

Module db3
    Public Sub Main(ByVal args() As String)

        ' برنامه کنسول
        ' اجرا می‌کند SQL پرس‌وجوهایی را که از طریق صفحه‌کلید وارد شده‌اند بر روی یک 
        'جدول ARTICLES در یک پایگاه داده DSN که نام آن به‌عنوان پارامتر ارسال می‌شود
        Const syntaxe As String = "syntaxe : pg dsnArticles"

        'بررسی پارامتر
        'آیا دو پارامتر وجود دارد
        If args.Length <> 1 Then
            ' پیام خطا
            Console.Error.WriteLine(syntaxe)
            'پایان
            Environment.Exit(1)
        End If        'if
        ' بازیابی پارامتر
        Dim dsnArticles As String = args(0)
        ' رشته اتصال پایگاه داده
        Dim connectString As String = "DSN=" + dsnArticles + ";"

        ' آماده‌سازی اتصال پایگاه داده
        Dim articlesConn As OdbcConnection = Nothing
        Dim sqlCommand As OdbcCommand = Nothing
        Try
            ' در حال تلاش برای دسترسی به پایگاه داده
            articlesConn = New OdbcConnection(connectString)
            articlesConn.Open()
            ' ایجاد یک شیء فرمان
            sqlCommand = New OdbcCommand("", articlesConn)
            'تلاش
        Catch ex As Exception
            ' پیام خطا
            Console.Error.WriteLine(("Erreur d'exploitation de la base de données (" + ex.Message + ")"))
            'منابع آزاد شدند
            Try
                articlesConn.Close()
            Catch
            End Try
            Environment.Exit(2)
        End Try        'catch
        ' یک فرهنگ لغت از دستورات SQL پذیرفته‌شده ساخته می‌شود
        Dim commandesSQL() As String = {"select", "insert", "update", "delete"}
        Dim dicoCommandes As New Hashtable
        Dim i As Integer
        For i = 0 To commandesSQL.Length - 1
            dicoCommandes.Add(commandesSQL(i), True)
        Next i

        'خواندن و اجرای دستورات واردشده از طریق صفحه‌کلید SQL
        Dim requête As String = Nothing        ' texte de la requête SQL
        Dim champs() As String        ' les champs de la requête    
        Dim modèle As New Regex("\s+")
        'حلقه برای وارد کردن و اجرای دستورات SQL تایپ‌شده روی صفحه‌کلید
        While True
            ' بدون خطا در شروع
            Dim erreur As Boolean = False
            ' درخواست پرس‌وجو
            Console.Out.Write(ControlChars.Lf + "Requête SQL (fin pour arrêter) : ")
            requête = Console.In.ReadLine().Trim().ToLower()
            ' تمام شد؟
            If requête = "fin" Then
                Exit While
            End If
            ' شکستن پرس‌وجو به فیلدها
            champs = modèle.Split(requête)
            'آیا پرس‌وجو معتبر است؟
            If champs.Length = 0 Or Not dicoCommandes.ContainsKey(champs(0)) Then
                ' پیام خطا
                Console.Error.WriteLine("Requête invalide. Utilisez select, insert, update, delete")
                ' پرس‌وجوی بعدی
                erreur = True
            End If
            If Not erreur Then
                'آماده‌سازی شیء Command برای اجرای پرس‌وجو
                sqlCommand.CommandText = requête
                ' اجرای پرس‌وجو
                Try
                    If champs(0) = "select" Then
                        executeSelect(sqlCommand)
                    Else
                        executeUpdate(sqlCommand)
                    End If
                Catch ex As Exception
                    ' پیام خطا
                    Console.Error.WriteLine(("Erreur d'exploitation de la base de données (" + ex.Message + ")"))
                End Try
            End If
        End While
        'آزادسازی منبع
        Try
            articlesConn.Close()
        Catch
        End Try
        Environment.Exit(0)
    End Sub

    ' اجرای یک پرس‌وجوی به‌روزرسانی
    Sub executeUpdate(ByVal sqlCommand As OdbcCommand)
        'اجرای پرس‌وجوی به‌روزرسانی sqlCommand
        Dim nbLignes As Integer = sqlCommand.ExecuteNonQuery()
        ' نمایش
        Console.Out.WriteLine(("Il y a eu " & nbLignes & " ligne(s) modifiée(s)"))
    End Sub

    ' اجرای یک پرس‌وجوی SELECT
    Sub executeSelect(ByVal sqlCommand As OdbcCommand)
        ' اجرای sqlCommand، یک پرس‌وجوی SELECT
        Dim myReader As OdbcDataReader = sqlCommand.ExecuteReader()
        'پردازش جدول بازیابی‌شده
        'نمایش ستون‌ها
        Dim ligne As String = ""
        Dim i As Integer
        For i = 0 To (myReader.FieldCount - 1) - 1
            ligne += myReader.GetName(i) + ","
        Next i
        ligne += myReader.GetName(i)
        Console.Out.WriteLine((ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf + ligne + ControlChars.Lf + "".PadLeft(ligne.Length, "-"c) + ControlChars.Lf))
        'نمایش داده‌ها
        While myReader.Read()
            'پردازش سطر فعلی
            ligne = ""
            For i = 0 To myReader.FieldCount - 1
                ligne += myReader(i).ToString + " "
            Next i
            'نمایش
            Console.WriteLine(ligne)
        End While
        'آزادسازی منابع
        myReader.Close()
    End Sub
End Module

ما در اینجا تنها درباره آنچه نسبت به برنامه قبلی جدید است، توضیح می‌دهیم:

  • ما در حال ساخت یک فرهنگ لغت از دستورات پذیرفته‌شده SQL هستیم:

         'ساخت فرهنگ لغت دستورات پذیرفته‌شده SQL
        Dim commandesSQL() As String = {"select", "insert", "update", "delete"}
        Dim dicoCommandes As New Hashtable
        Dim i As Integer
        For i = 0 To commandesSQL.Length - 1
            dicoCommandes.Add(commandesSQL(i), True)
        Next i

که سپس به ما این امکان را می‌دهد تا به سادگی بررسی کنیم که آیا اولین کلمه (میدان [0]) از پرس‌وجوی تایپ‌شده یکی از چهار فرمان پذیرفته‌شده است:


             ' آیا پرس‌وجو معتبر است؟
            If champs.Length = 0 Or Not dicoCommandes.ContainsKey(champs(0)) Then
                ' پیام خطا
                Console.Error.WriteLine("Requête invalide. Utilisez select, insert, update, delete")
                 ' پرس‌وجوی بعدی
                erreur = True
            End If            'if
  • قبلاً، پرس‌وجو با استفاده از متد Split از کلاس RegEx به فیلدها تقسیم شده بود:

        Dim modèle As New Regex("\s+")
....
            ' پرس‌وجو به فیلدها تقسیم می‌شود
            champs = modèle.Split(requête)

کلمات تشکیل‌دهندهٔ پرس‌وجو می‌توانند با هر تعداد فاصله از هم جدا شوند.

  • اجرای پرس‌وجویی مانند select از روش یکسان با پرس‌وجوی به‌روزرسانی (insert, update, delete) استفاده نمی‌کند. بنابراین، باید یک آزمون انجام شود و برای هر یک از این دو مورد، تابع متفاوتی اجرا شود:

                 'آماده‌سازی شیء Command برای اجرای پرس‌وجو
                sqlCommand.CommandText = requête
                 ' اجرای پرس‌وجو
                Try
                    If champs(0) = "select" Then
                        executeSelect(sqlCommand)
                    Else
                        executeUpdate(sqlCommand)
                    End If                    'try
                Catch ex As Exception
                    ' پیام خطا
                    Console.Error.WriteLine(("Erreur d'exploitation de la base de données (" + ex.Message + ")"))
                End Try

اجرای پرس‌وجوی SQL ممکن است یک استثنا ایجاد کند که در اینجا مدیریت می‌شود.

  • تابع executeSelect همه موارد پوشش‌داده‌شده در مثال‌های قبلی را در بر می‌گیرد.
  • تابع executeUpdate از متد ExecuteNonQuery در کلاس OdbcCommand استفاده می‌کند که تعداد خطوط تحت تأثیر دستور را برمی‌گرداند.

7.3.5. IMPOTS

اکنون به سراغ شیء impôt می‌رویم که در فصل قبلی ایجاد شده است:


' گزینه‌ها
Option Strict On
Option Explicit On 

' فضاهای نام
Imports System

Public Class impôt
    'داده‌های مورد نیاز برای محاسبه مالیات
    'از یک منبع خارجی می‌آید
    Private limites(), coeffR(), coeffN() As Decimal

    ' تولیدکننده
    Public Sub New(ByVal LIMITES() As Decimal, ByVal COEFFR() As Decimal, ByVal COEFFN() As Decimal)
        ' ما بررسی می‌کنیم که سه جدول اندازه یکسانی داشته باشند
        Dim OK As Boolean = LIMITES.Length = COEFFR.Length And LIMITES.Length = COEFFN.Length
        If Not OK Then
            Throw New Exception("Les 3 tableaux fournis n'ont pas la même taille(" & LIMITES.Length & "," & COEFFR.Length & "," & COEFFN.Length & ")")
        End If
        ' همه چیز درست است
        Me.limites = LIMITES
        Me.coeffR = COEFFR
        Me.coeffN = COEFFN
    End Sub

    'محاسبه مالیات
    Public Function calculer(ByVal marié As Boolean, ByVal nbEnfants As Integer, ByVal salaire As Integer) As Long
        'محاسبه تعداد سهام
        Dim nbParts As Decimal
        If marié Then
            nbParts = CDec(nbEnfants) / 2 + 2
        Else
            nbParts = CDec(nbEnfants) / 2 + 1
        End If
        If nbEnfants >= 3 Then
            nbParts += 0.5D
        End If
        'محاسبه درآمد مشمول مالیات و ضریب خانوادگی
        Dim revenu As Decimal = 0.72D * salaire
        Dim QF As Decimal = revenu / nbParts
        'محاسبه مالیات
        limites((limites.Length - 1)) = QF + 1
        Dim i As Integer = 0
        While QF > limites(i)
            i += 1
        End While
        ' نتیجه بازگشت
        Return CLng(revenu * coeffR(i) - nbParts * coeffN(i))
    End Function
End Class

ما یک سازنده جدید به آن اضافه می‌کنیم که امکان инициалиزه شدن آرایه‌های limites، coeffR و coeffN از یک پایگاه داده ODBC را فراهم می‌کند:


Imports System.Data
Imports Microsoft.Data.Odbc
Imports System.Collections
...


    ' سازنده ۲
    Public Sub New(ByVal DSNimpots As String, ByVal Timpots As String, ByVal colLimites As String, ByVal colCoeffR As String, ByVal colCoeffN As String)
        ' سه جدول محدوده را، coeffR، coeffN، بر اساس
        'محتویات جدول Timpots در پایگاه داده ODBC DSNimpots
        '، colLimites، colCoeffR و colCoeffN سه ستون این جدول هستند
        'ممکن است یک استثنا پرتاب کند
        Dim connectString As String = "DSN=" + DSNimpots + ";"        ' chaîne de connexion à la base
        Dim impotsConn As OdbcConnection = Nothing        ' la connexion
        Dim sqlCommand As OdbcCommand = Nothing        ' la commande SQL
        'پرس‌وجوی SELECT
        Dim selectCommand As String = "select " + colLimites + "," + colCoeffR + "," + colCoeffN + " from " + Timpots
        'جداول برای بازیابی داده‌ها
        Dim tLimites As New ArrayList
        Dim tCoeffR As New ArrayList
        Dim tCoeffN As New ArrayList

        ' تلاشی برای دسترسی به پایگاه داده انجام می‌شود
        impotsConn = New OdbcConnection(connectString)
        impotsConn.Open()
        ' یک شیء فرمان در حال ایجاد است
        sqlCommand = New OdbcCommand(selectCommand, impotsConn)
        ' اجرای پرس‌وجو
        Dim myReader As OdbcDataReader = sqlCommand.ExecuteReader()
        ' پردازش جدول بازیابی‌شده
        While myReader.Read()
            'داده‌ها از سطر جاری در آرایه‌ها قرار می‌گیرند
            tLimites.Add(myReader(colLimites))
            tCoeffR.Add(myReader(colCoeffR))
            tCoeffN.Add(myReader(colCoeffN))
        End While
        'منابع آزاد می‌شوند
        myReader.Close()
        impotsConn.Close()

        'آرایه‌های پویا به آرایه‌های ایستا تبدیل می‌شوند
        Me.limites = New Decimal(tLimites.Count) {}
        Me.coeffR = New Decimal(tLimites.Count) {}
        Me.coeffN = New Decimal(tLimites.Count) {}
        Dim i As Integer
        For i = 0 To tLimites.Count - 1
            limites(i) = Decimal.Parse(tLimites(i).ToString())
            coeffR(i) = Decimal.Parse(tCoeffR(i).ToString())
            coeffN(i) = Decimal.Parse(tCoeffN(i).ToString())
        Next i
    End Sub

برنامهٔ آزمون به شرح زیر است: این برنامه به‌عنوان آرگومان، پارامترهایی را که باید به سازندهٔ کلاس impôt ارسال شوند، دریافت می‌کند. پس از ساخت یک شیء impôt، مالیات قابل پرداخت را محاسبه می‌کند:


Option Explicit On 
Option Strict On

' فضاهای نام
Imports System
Imports Microsoft.VisualBasic

' صفحهٔ آزمایشی
Module testimpots
    Sub Main(ByVal arguments() As String)
        ' برنامه تعاملی محاسبه مالیات
        ' کاربر سه مورد داده را از طریق صفحه‌کلید وارد می‌کند: متأهل nbEnfants حقوق
        ' سپس برنامه مالیات قابل پرداخت را نمایش می‌دهد
        Const syntaxe1 As String = "pg DSNimpots tabImpots colLimites colCoeffR colCoeffN"
        Const syntaxe2 As String = "syntaxe : marié nbEnfants salaire" + ControlChars.Lf + "marié : o pour marié, n pour non marié" + ControlChars.Lf + "nbEnfants : nombre d'enfants" + ControlChars.Lf + "salaire : salaire annuel en F"

        'بررسی پارامترهای برنامه
        If arguments.Length <> 5 Then
            ' پیام خطا
            Console.Error.WriteLine(syntaxe1)
            'پایان
            Environment.Exit(1)
        End If        'if
        ' بازیابی آرگومان‌ها
        Dim DSNimpots As String = arguments(0)
        Dim tabImpots As String = arguments(1)
        Dim colLimites As String = arguments(2)
        Dim colCoeffR As String = arguments(3)
        Dim colCoeffN As String = arguments(4)

        'ایجاد یک شیء مالیاتی
        Dim objImpôt As impôt = Nothing
        Try
            objImpôt = New impôt(DSNimpots, tabImpots, colLimites, colCoeffR, colCoeffN)
        Catch ex As Exception
            Console.Error.WriteLine(("L'erreur suivante s'est produite : " + ex.Message))
            Environment.Exit(2)
        End Try

        'حلقه بی‌نهایت
        While True
            ' در ابتدا هیچ خطایی وجود ندارد
            Dim erreur As Boolean = False

            ' درخواست پارامترها برای محاسبه مالیات
            Console.Out.Write("Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :")
            Dim paramètres As String = Console.In.ReadLine().Trim()

            ' کاری هست که باید انجام شود؟
            If paramètres Is Nothing Or paramètres = "" Then
                Exit While
            End If

            ' بررسی تعداد آرگومان‌ها در خط واردشده
            Dim args As String() = paramètres.Split(Nothing)
            Dim nbParamètres As Integer = args.Length
            If nbParamètres <> 3 Then
                Console.Error.WriteLine(syntaxe2)
                erreur = True
            End If
            Dim marié As String
            Dim nbEnfants As Integer
            Dim salaire As Integer
            If Not erreur Then
                ' بررسی اعتبار پارامترها
                ' متأهل
                marié = args(0).ToLower()
                If marié <> "o" And marié <> "n" Then
                    Console.Error.WriteLine((syntaxe2 + ControlChars.Lf + "Argument marié incorrect : tapez o ou n"))
                    erreur = True
                End If
                ' nbEnfants
                nbEnfants = 0
                Try
                    nbEnfants = Integer.Parse(args(1))
                    If nbEnfants < 0 Then
                        Throw New Exception
                    End If
                Catch
                    Console.Error.WriteLine(syntaxe2 + "\nArgument nbEnfants incorrect : tapez un entier positif ou nul")
                    erreur = True
                End Try
                ' حقوق
                salaire = 0
                Try
                    salaire = Integer.Parse(args(2))
                    If salaire < 0 Then
                        Throw New Exception
                    End If
                Catch
                    Console.Error.WriteLine(syntaxe2 + "\nArgument salaire incorrect : tapez un entier positif ou nul")
                    erreur = True
                End Try
            End If
            If Not erreur Then
                'پارامترها صحیح هستند – مالیات محاسبه شده است
                Console.Out.WriteLine(("impôt=" & objImpôt.calculer(marié = "o", nbEnfants, salaire).ToString + " F"))
            End If
        End While
    End Sub
End Module

پایگاه دادهٔ مورد استفاده یک پایگاه دادهٔ MySQL به نام DSN mysql-impots است:

C:\mysql\bin>mysql --database=impots --user=admimpots --password=mdpimpots
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5 to server version: 3.23.49-max-debug

Type 'help' for help.

mysql> show tables;
+------------------+
| Tables_in_impots |
+------------------+
| timpots          |
+------------------+

mysql> select * from timpots;
+---------+--------+---------+
| limites | coeffR | coeffN  |
+---------+--------+---------+
|   12620 |      0 |       0 |
|   13190 |   0.05 |     631 |
|   15640 |    0.1 |  1290.5 |
|   24740 |   0.15 |  2072.5 |
|   31810 |    0.2 |  3309.5 |
|   39970 |   0.25 |    4900 |
|   48360 |    0.3 |    6898 |
|   55790 |   0.35 |  9316.5 |
|   92970 |    0.4 |   12106 |
|  127860 |   0.45 |   16754 |
|  151250 |    0.5 | 23147.5 |
|  172040 |   0.55 |   30710 |
|  195000 |    0.6 |   39312 |
|       0 |   0.65 |   49062 |
+---------+--------+---------+

اجرای برنامه آزمون نتایج زیر را تولید می‌کند:

dos>D:\data\devel\vbnet\poly\chap6\impots>vbc /r:system.data.dll /r:microsoft.data.odbc.dll /r:system.dll /t:library impots.vb

dos>vbc /r:impots.dll testimpots.vb

dos>test mysql-impots timpots limites coeffr coeffn
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :o 2 200000
impôt=22506 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :n 2 200000
impôt=33388 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :o 3 200000
impôt=16400 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :n 3 300000
impôt=50082 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :n 3 200000
impôt=22506 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :