* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Tirgul9 - FTP Directory Listing
Survey
Document related concepts
Transcript
Enterprise Development Using Visual Basic 6.0 Autumn 2002 Tirgul #9 ‘Tirgul’ # 9 Objectives • Understanding ADO • Using DSN/DSN’less connection • In-depth: – Connection – RecordSet – Command ‘Tirgul’ #9 3-Tier Architecture ‘Tirgul’ #9 The Data Access Layer • Almost any enterprise application have some needs to access data (database, web, email, legacy data..) • Microsoft has developed a technology to make this task simple for us • VB makes it easy to use ‘Tirgul’ #9 The Problem • Each data source has different way to access it SQL Data •SQL Server •Oracle •Informix •DB2 •Fox Pro •Jet Non SQL Data •Mail •Video •Text •Web •... ‘Tirgul’ #9 Mainframe and Legacy Data The Solution • Single high level,efficient programming, paradigm to work with everything it is called: universal data access (UDA) • The programmer can use the same code to access any data! ‘Tirgul’ #9 What is UDA? • UDO Consist of: – ActiveX Data Objects(ADO) – OLE DB – And other… Together these interfaces provide us the means to work with any data ‘Tirgul’ #9 UDA Architecture Data consumer Application (VB, VC++,ASP) ADO Data Providers OLE DB SQL Data •SQL Server •Oracle •Fox Pro •Jet Non SQL Data 0 •Mail •Video •Text •Web ‘Tirgul’ #9 Mainframe and Legacy Data What is ADO? • • ADO is one of the components of the UDA model. Other components: – Remote Data Services (RDS) – OLE DB is Microsoft's component database architecture that provides universal data integration over an enterprise's network— from mainframe to desktop - regardless of the data type – Open Database Connectivity (ODBC) provide a unified way to access relational data as part of the OLE DB specification ‘Tirgul’ #9 ADO Layer ‘Tirgul’ #9 Ado Object Model Overview • High level, language independent, data access interface • Provides layer to the underplaying data source (OLE DB Provider) • Object Oriented interface for accessing data • ADO is small, lightweight, fast, and feature complete – everything you need when you are programming either for the database applications or the Internet ‘Tirgul’ #9 ADO Objects • object-based interface that provides a logical set of objects you can access from code Object Functionality Connectio n Command Manages the connection with the data source Defines the commands that will be executed against the data source Contains the data that is retrieved from the data source Recordset ‘Tirgul’ #9 ADO Objects • ADO objects are not dependant on one another. you can create instances of objects independently of one another, for example, you can create a Recordset object without creating a connection object. • Unlike the older technologies, ADO is more flexible, ADO code is easier to write, read and maintain. • ADO is built on top of OLE DB and is capable of accessing any sort of data that is wrapped and exposed by an appropriate OLE DB provider. ‘Tirgul’ #9 Basic ADO operations • • • • • • Select Query Update Query Delete Query Integrity Constraints (PK/FK) Transactions (Begin, Commit, Rollback) Stored Procedures ‘Tirgul’ #9 ADO Objects • • • • • • • • Connection Recordset Command Parameter Error Field Property Stream ‘Tirgul’ #9 The Connection Object • The connection object enable us to connect to data stores. • In this object we specify which: – OLE DB provider we wish to use. – Security details for the connection. – And other specific details. • NOTE: in some cases you do not have to define a connection object. Then ADO will create one for you. as a rule, always define connection object explicitly. ‘Tirgul’ #9 The Command Object • The command object is designed for running command against a data store • You may also execute command using the connection object but these command have restrictions. ‘Tirgul’ #9 The Recordset Object • The most commonly used object. • It contains a set of data we extract from the data stores. • The Recordset holds the record that are usually fetched from a query • It allows us to: – Change the data (update, delete, add). – Iterate the records. – Filter the record so that only a subset is shown. • A Recordset also has a fields collection where there is a filed object for each column in the Recordset ‘Tirgul’ #9 DISPLAYING DATA WITH A RECORDSET (USING A CONNECTION OBJECT) Set Con = new ADODB.Connection Set RS = new ADODB.Recordset Con.open “DSN=myDB;UID=sa;Password=;” RS.ActiceConnection = Con RS.open “select * from Users” while not RS.EOF msgBox RS.fields(“fname”).values RS.MoveNext Wend RS.Close Con.Close ‘Tirgul’ #9 DISPLAYING DATA WITH A RECORDSET (USING A CONNECTION OBJECT 2) StrConnect = “DSN=myDB;UID=sa;Password=;” Set Con = new ADODB.Connection Con.open “DSN=myDB;UID=sa;Password=;” Set RS =new ADODB.Recordset RS.Open “select * from Users”, Con, adopenkeyset,adlockoptimistic while not objRec.EOF msgBox RS.fields(“fname”).values RS.MoveNext Wend RS.Close ‘Tirgul’ #9 DISPLAYING DATA WITH A RECORDSET (WITHOUT A CONNECTION OBJECT) StrConnect = “DSN=myDB;UID=sa;Password=;” Set RS =new ADODB.Recordset RS.Open “select * from Users”,strConnect, adopenkeyset, adlockoptimistic while not objRec.EOF msgBox RS.fields(“fname”).values RS.MoveNext Wend RS.Close ‘Tirgul’ #9 ADO 2.5 Extensions • • • • Record Object Stream Object Not in this course scope Mainly for handling non relation data such as File System, Email System XML Files.. ‘Tirgul’ #9 ADO Collections • There are several collections in the ADO object library. – Fields collection. • This collection is a member of the Recordset object. • Each member of the collection is filed object. • In SQL structured data the field correspond to a column and contains information about the column: – Name, data type, length.. ‘Tirgul’ #9 ADO Collections – Cont. • There several other collections: – Parameter – part of the command object – Errors – part of the connection object – Properties ‘Tirgul’ #9 Connecting to Data Source • In order to access some data source, you have to connect to it using the connection object. • The actual method of connecting to the data store is the same for all stores. • The actual details may be different between different providers • There are several ways to connect to data source: – Using a connection string – DSN’less – Using ODBC data source – DSN – Using data link file ‘Tirgul’ #9 DSN • DSN = 'Data Source Name' • DSN is an easy way to assign useful and meaningful names to data sources which may not be limited to databases alone (e.g Excel spread sheet etc.) ‘Tirgul’ #9 Creating a DSN (1) • Database exists • ODBC32 exists (Check control panel) – Go into Control Panel – NT ONLY - Go into Administration Tools – Look for ODBC Data Sources (32-bit) or Data Sources (ODBC) ‘Tirgul’ #9 Creating a DSN (2) • Go into Control Panel • Then Administrative Tools ‘Tirgul’ #9 Creating a DSN (3) • Then ODBC Data Sources (or some sort of ODBC) ‘Tirgul’ #9 Creating a DSN (4) • Then click on the System DSN tab and click on add User DSN - DSN's for you only. System DSN - The whole system can see these they are ones that everyone that accesses your computer can see. ‘Tirgul’ #9 Creating a DSN (5) • Choose your driver ‘Tirgul’ #9 Creating a DSN (6) • Set up the DSN Enter a Data Source Name, this is what we call your Database, so keep it short and without spaces. eg. myBooks Click on Select... to browse to the directory where your database is and choose it, this tells ODBC where you find the DB (well duh!) If you set a password for your database click on Advanced... ‘Tirgul’ #9 Creating a DSN (7) • Passwords? Access only supports passwords, not usernames, so just enter the password and click OK. Click OK to the other dialog and you can see your DSN listed in the System DSN list, now you can use it to set up databases. ‘Tirgul’ #9 Create the Northwind DSN • Northwind is a sample Access DB. • It comes with Microsoft office installation. • Use ‘Search’.. ‘Tirgul’ #9 Add Northwind DSN– Select Access Driver Select Access Driver ‘Tirgul’ #9 Add Northwind DSN – Select Data base Use Select to select database ‘Tirgul’ #9 Add Northwind DSN – Browse for Northwind ‘Tirgul’ #9 Add Northwind DSN – Set name and description ‘Tirgul’ #9 Add Northwind DSN – Done, new in the list Northwind added ‘Tirgul’ #9 DSN vs DSN less Database Connections • you can connect to DSN using following code: Dim con as new ADODB.Connection DSN Name only Other data is hidden in the DSN itself con.Open "DSN=myDSN" …Use Connection con.Close Set con = Nothing ‘Tirgul’ #9 DSN’less Connection • DSN’less connection does not require creation of system level DSNs for connecting to databases and provide an alternative to DSNs. • We will now see how to connect to a database using Connection String in place of DSN name. ‘Tirgul’ #9 DSN less Connection String Dim con as new ADODB.Connection con.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data“ & _ "Source=c:\path\to\database.mdb" …Use Connection con.Close Set con = Nothing ‘Tirgul’ #9 All Connection Data Why to use DSN Connections ? • Provides meaningful data source names. • When there are lots of data sources to think of and you want a central repository to hold a collection of data sources without having to worrying about the actual configuration of the data source. ‘Tirgul’ #9 Why to use DSN less Connections ? • When you can't register DSNs yourself e.g. when you are running a virtual hosting account on other's server. Stop emailing system administrator, connect to your databases directly. • Provides faster database access because it uses native OLE DB providers which provide faster database connection. ‘Tirgul’ #9 ADO Connection String • For MS Access database: Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\somefolder\mydatabase.mdb; User ID=admin; Password=; • For MS SQL Server: Provider=SQLOLEDB; Data Source=server_name_or_address; Initial Catalog=database_name; User ID=username; Password=password; Network Library=dbmssocn; ‘Tirgul’ #9 Building a Connection String • Create a UDL file – Right click on Desktop, New -> Text File, rename to filename.UDL • Double-click the UDL file • Select Microsoft.Jet.OLEDB.4.0 ‘Tirgul’ #9 Building a Connection String (cont.) • Click Next >> • Browse for the Access database • Enter login information if necessary ‘Tirgul’ #9 Building a Connection String (cont.) • Click OK • Open the UDL file using Notepad ‘Tirgul’ #9 Connection – Open Method • The connection object has an open method: – Connection.Open [connetionstring], [user id], [password], [options] ConnectionString The String containing the connection details UserID The name of the user during the connection. Overides the user name in the connection string Password Same as user but password Options adAsyncConnect or empty ‘Tirgul’ #9 Establishing a SQL Database Connection Set a reference to the ADO object library To set a reference to the ADO Library in VB, click the Project menu, and click Reference. Then select the appropriate reference Declare a Connection Object Dim conn as ADODB.Connection Set conn = new ADODB.Connection Specify an OLE DB Data Provider Conn.Provider = “SQLOLEDB” Specify Connection Information Use the connection string property to specify any additional information strCnn = "Data Source=ds;uid=sa;pwd=;” & _ database=pubs;Initial Catalog=pubs" Open a connection Use the open method to establish connection to the data source conn.open strCnn ‘Tirgul’ #9 Opening a Connection ‘Tirgul’ #9 Closing a Connection • When you finished working with the data source, use close method of the connection object. – Free any associated system resources – Close any active Recordset associates with this connection – Set the object to nothing in order to move the object from memory Conn.Close Set Conn = nothing – NOTE: connection will be closed automatically when the connection variable goes out of scope or set to nothing – Closing connection is very important for scalability and performance especially when it is being used over the web (connection pooling) ‘Tirgul’ #9 The Connection Object - Interface • Properties • Methods – CommandTimeout – BeginTrans – ConnectionString – Close – ConnectionTimeout – CommitTrans – CursorLocation – Execute – DefaultDatabase – Open – IsolationLevel – OpenSchema – Mode – RollbackTrans – Provider – State – Version • Collections – Errors – Properties ‘Tirgul’ #9 Recordsets • Recordset contains the data as a table. • Knowing the details of how the data is held is and manipulated is essential. • It allows you to make informed decision of what type of Recordset you are going to use. ‘Tirgul’ #9 Recordset & Cursors • Like every other object a Recordset has data, methods and state. • Each Recordset set has one pointer to the current record. • The curser is what manage the set of records and the current location within the record • When you iterate through records, the cursor performs the move. When you try to move beyond the last record the curser handles it. ‘Tirgul’ #9 Recordset & Cursors Current Record ID 111111 222222 333333 Name Bob Mary Bil Cursor Engine ‘Tirgul’ #9 Phone 555555 666666 777777 Cursors Type • Static (adOpenStatic). – Contains a static copy of the record – The content of the Recordset are at the time the record is being created. – Any record modified, added or deleted by other user will not be visible. – Movement through the Recordset is allowed both forward and backward • Forward only (adOpenForward) – The default cursor type – Identical to static except you can only move forward through the Recordset ‘Tirgul’ #9 Cursor Types – Cont. • Dynamic (adOpenDynamic). – Doesn’t have fixed set of records – Any changes by other users will be visible in the Recordset – Movement is allowed in both directions • Keyset (adOpenKeyset). – Like dynamics, any changes are visible except new records. – If other user delete a record this record will be inaccessible by the Recordset ‘Tirgul’ #9 Performance issue • Why are static cursor are slower the forward –only cursor? – Forward cursor do no have to keep any track about records they past, static do! • If you just want to look at the records in order to build a table, what kind of cursor would you be using? – Forward only ‘Tirgul’ #9 Recordset and Locks • Before getting into recordset creation and manipulation. There is another last topic – Locks • Locking is a mechanism to ensure Integrity of the data, making sure that changes aren’t overwritten • We want to make sure that my changes of the data will be overwritten by other user changes • To manage this protection we use locking. • There are several type of recordset locks ‘Tirgul’ #9 Lock types • Lock Types: – Read Only (adLockReadOnly) – The default locking type. Recordset is read only. – Pessimistic (adLockPessimistic) – Locking a record whenever editing is taking place – Optimistic (adLockOptmistic) – The record is not locked until changes to the data are committed to the data store – Batch Optimistic (adLockBatchOptimistic). Allows multiple records to be modified, and the records are only locked when the UpdateBatch method is called ‘Tirgul’ #9 Performance issue • If you do not need to modify records what locking would you be using? – Read-only • Pessimistic insures more integrity, why not use it always? – Concurrency, a locked records is available to other user therefore concurrency is reduced ‘Tirgul’ #9 Creating a Recordset • Creating Recordset is achieved by using the open method • Recordset.Open [source] , [ActiveConnection] , [CursorType] , [LockType], [options] Source The source of the data. Can be the name of the table is the database, an SQL string, a stored procuder or a command object ActiveConnection The connection to use for this connection. Can be an open Connection object or a connection string CursorType The type of cursor to use. The default is adForwardOnly LockType The type of locking to use. The default is adLockReadOnly Options Tells the provider what the source argument is – that is, whether is is a table, a text string and so on ‘Tirgul’ #9 Creating Recordset An opened connection object ‘Tirgul’ #9 The Recordset Object • Properties • AbsolutePage, AbsolutePosition, ActiveConnection, BOF, Bookmark, CacheSize, CursorLocation, CursorType, EditMode, EOF, Filter, LockType, MarshalOptions, MaxRecords, PageCount, PageSize, RecordCount, Source, State, Status • • Collections – Fields, Properties ‘Tirgul’ #9 Methods – AddNew, CancelBatch, CancelUpdate, Clone, Close, Delete, GetRows, Move, MoveFirst, MoveLast, MoveNext, MovePrevious, NextRecordset, Open, Requery, Resync, Supports, Update, UpdateBatch Navigating Through Records • Once you opened a record you often need to loop through each record rsAuthors.Open “authors” , conn Do While Not rsAuthors.EOF Debug.Print rsAuthors(“au_lname”) & “,” & _ rsAuthors(“au_fname”) rsAuthors.MoveNext Loop EOF property is true when the end of the Recordset has been reached • If your Recordset allow moving backwards you can use MovePrevious and check the BOF property • There are also MoveFirst , MoveLast and Move methods ‘Tirgul’ #9 Using the Fields Collection • The fields collection contains a field for each column in the Recordset. • The fields collection is the default collection and therefore can be omitted when accessing fields. • The following example all return the same result. ‘Tirgul’ #9 Using the Fields Collection rsAuthors.Fileds(“au_lname”).Value rsAuthors(“au_lname).Value Default collection rsAuthors(1).Value rsAuthors.Fields(1).Value rsAuthors(“ay_lname”) Default collection & Property rsAuthors(1) Don’t forget to use Trim when add/Select a String ‘Tirgul’ #9 Using the Fields Collection To Get Meta Data ‘Tirgul’ #9 Bookmarks • When you are moving around the Recordset you might want to retain the position of a record and then move back to it later • A Recordset move bookmark holds a unique pointer to an individual record • To Bookmark you simple assign the bookmark property to a variable Dim varBkMark as Variant varBkMark = rsAuthors.BookMark • To return to the bookmark position you do the opposite rsAuthors.BookMark = varBkMark NOTE: Not all records support Bookmarks. The support method allows you to identify that If rsAuthors.Support(adBookmark) then… ‘Tirgul’ #9 Filtering Recordsets • Filtering is a way to temporarily restricting the view of records in a Recordset • It is useful if you want to show subset of records without re-queering the data store rsAuthors.Filter rsAuthors.Filter rsAuthors.Filter rsAuthors.Filter = = = = “State=‘ca’” “au_lname = ‘homer’ or au_lname = ‘Francis’” “au_lname LIKE ‘Ho%’” “” ‘Reset filtering ‘Tirgul’ #9 Filtering With Constants • The filter property can also take one of the FilterGroupEnum constants as its argument. These are: – adFilterNone – removes current filter – adFilterpendingRecords – to view only records that have changed but not yet been sent to server (batch update move) • Look in the MSDN for the other constants ‘Tirgul’ #9 Filtering with Bookmarks The filter is applied on the bookmarks array The Array function must be used to convert the individual bookmark to a variant array ‘Tirgul’ #9 Searching for Record • Searching for individual records is performed using the find method rsAuthors.Find = “au_lname = ‘loyd’” • • You can only have one criterion – And or Or is not allowed You can use optional argument to specify extra options Recordset.Find = Criteria , [SkipRow], [SearchDirection],[Start] SkipRow Number of rows to skip before search (0 by default) SearchDirection Can be either adSearchForward or adSearchBackWard Start Start is a Bookmark identifing where to start from • • If record is found you are placed at that record Else you are either at EOF or BOF depending on the search direction ‘Tirgul’ #9 Searching for Record – Using Bookmark ‘ Save current position varBkmk = rsAuthors.BookMark ‘Find the Record rsAuthors.Find “au_lname = ‘Sussman’” ‘Was it found If Not rsAuthors.EOF then Debug.write “Found: “ & rsAuthors(“au_lname”) Else Debug.write “Not Found. Moving” rsAuthors.Bookmark = varBkmk End If ‘Tirgul’ #9 Modifying Records • Up to now we saw methods and properties to query the Recordset. • However many times we want to modify records: – Using: Add, delete, update.. • Modifying records can be done both using the Connection, Command and Recordset objects. • Each method has advantages and disadvantages. To modify a record in recordset you must have locking type other than AdLockReadOnly – remember this is the default. ‘Tirgul’ #9 Adding Records using Recordset • There are two ways to add records, both use the AddNew method: With rsAuthors .Open “authors”, conn, adOpenDynamic, _ adLockOpimistic, adCmdTableDirect .AddNew .Fields(“ui_id”) = “123-12-1234” .Fields(“au_lname”) = “Lloyd” .Fields(“au_fname”) = “Janine” .Fields(“Contract”) = 0 .Update End with Requires the Update method With rsAuthors .Open “authors”, conn, adOpenDynamic, _ adLockOpimistic, adCmdTableDirect .AddNew Array(“ui_id” , “au_lname” , “au_fname” , “Contract”), _ Array(“123-12-1234”, “Lloyd”, “Janine”, 0) End With ‘Tirgul’ #9 Editing Records using Recordset • Editing records is similar to the first method of inserting recordsthe difference being that you don’t need to call the AddNew method strSQL = “SELECT * FROM authors WHERE au_lname = ‘Lloyd’” With rsAuthors .Open strSQL , conn, adOpenDynamic, _ adLockOpimistic, adCmdTableDirect .Fields(“Contract”) = 1 .Update End with The example above simply set the “contract” field of the current record (in this case the first record) to 1 ‘Tirgul’ #9 Deleting Records using Recordset • To Delete records you call the Delete method. You may add optional argument from the Affect Enum constants – adAffectCurrent – delete the current record (default) – adAffectGroup – all records matching the current filter will be deleted – adAffectAll – all records in the recordset will be deleted rsAuthors.Delete Deletes the current record ‘Tirgul’ #9 Operations using Connection • All operations (Select/Add/Edit/Delete) could be executed using the Connection object: • For Select (Returned Recordset) Dim Conn As New ADODB.Connection Dim RS As ADODB.Recordset Set RS = Conn.Execute(SQLCommand, RecordsAffected) SQL command • For Add/Edit/Delete(No need for Recordset) Dim Conn As New ADODB.Connection Conn.Execute SQLCommand, RecordsAffected ‘Tirgul’ #9 Operations using Commend • All operations (Select/Add/Edit/Delete) could be executed using the Command object. • For a row-returning Command: Dim Command As New ADODB.Command Dim RS as new ADODB.RecordSet Set RS = Command.Execute( RecordsAffected, Parameters, Options ) • For a non–row-returning Command: Dim Command As New ADODB.Command Command.Execute RecordsAffected, Parameters, Options ‘Tirgul’ #9 Working with Command • Assume we have an open connection: Dim Command As New ADODB.Command Set Command.ActiveConnection = Conn Command.CommandText = strSQLCommand Command.Execute ‘Tirgul’ #9 Working with Command parameter • Common for stored procedures Dim adoCn As ADODB.Connection Dim adoCmd As ADODB.Command Dim adoParam As ADODB.Parameter Set adoCmd = New ADODB.Command With adoCmd .CommandType = adCmdStoredProc .CommandText = “SP_Cart_DeleteAll" '***Build parameters collection Set adoParam = .CreateParameter(Name:="RETURN_VALUE", Type:=adInteger,Direction:=adParamReturnValue) .Parameters.Append adoParam Set adoParam = .CreateParameter(Name:="@SessionID", Type:=adInteger, Size:=4,Direction:=adParamInput, Value:=SessionID) .Parameters.Append adoParam End With adoCmd.ActiveConnection = GetConnection() adoCmd.Execute ‘Tirgul’ #9 Working with Command parameter Public Const GET_STUDENT_DATA_QUERY = “Select * from Students where StudentID = ?” Dynamic variable Dim Command As New ADODB.Command Dim param as ADODB.Parameter Set Command.ActiveConnection = Conn Command.CommandText = GET_STUDENT_DATA_QUERY Command.CommandType = adCmdText Set param = MyCommand.CreateParameter(, adVarChar, adParamInputOutput, 50) param.value = “1” Command.Parameters.Append param Command.Execute ‘Tirgul’ #9 Auto Increment Field Problem • • Assume you have a table “tblTest” containing two files – ID – auto incremented integer – Name – text What will the following code produce? With rsData .Open “tblTest” , conn, adOpenDynamic, _ adLockOpimistic, adCmdTableDirect .AddNew .Fields(“Name”) = “Janine” .Update Debug.Print .Fields(“ID”) End with • Seems trivial but whether you can obtain this value after adding a new record depends upon the cursor type, lock type, and whether ID is indexed or not. ‘Tirgul’ #9 Auto Increment Field Problem • Any of the following combinations will return the new value Provider Target Indexed Cursor Location Cursor Type Lock Type Jet 4.0 Access97 Yes Server All All Access2000 Yes Server All All No Client All Pessimistic Optimistic Yes Server keySet Pessimistic Optimistic Client All Pessimistic Optimistic Client All Pessimistic Optimistic SQL OLE DB SQL Server 7.0 No ‘Tirgul’ #9 Managing Errors • When dealing with data store many run time errors may arise : – Security problems. – Synchronization – updating deleted record. – Connection – network.. • You can’t guarantee that every think is going to work perfectly. ‘Tirgul’ #9 The Errors Collection • The errors collection contains an error object for each error that accurred during a single ADO command. • The OLE DB provider set this objects. • Two important points to remember. – Each time an ADO command is executed, if an error occurs , the collection is cleared and filled. If no error occurs than the collection is untouched. – The OLE DB provider may fill the error collection with information and warning messages. These always have error number 0. ‘Tirgul’ #9 The Errors Collection • The collection is part of the connection object – Connection.Errors • You can also access the collection from the Recordset object – rsAuthors.ActiveConnection.Errors For Each errAuthors in rsAuthors.ActiveConnection.Errors ‘Handle/Display Error Next ‘Tirgul’ #9 The Error Object • Each member of the errors collection is an error type Property Description Number The ADO Error number NativeError The error number from the data provider SQLState The 5 digit SQL state code for the error, when connecting to an SQL database Source The Object that generated the error Description Descriptive text of the error ‘Tirgul’ #9