Creating New Data Access Objects

As mentioned in the section Creating Object Variables earlier in this chapter, Access 97 lets you create new DAOs with Access VBA code. The most common DAOs you create with Access VBA are Recordset and QueryDef objects. QueryDef objects, like TableDef objects, are called persistent objects because QueryDef and TableDef objects also are Document objects: Query and Table objects, respectively. QueryDef and TableDef objects are stored as elements of your .mdb file and appear in the Queries and Tables lists, respectively, of the Database window. Recordset objects are impersistent objects; they exist in memory only from the time you open them until they are closed. You can close a Recordset object by applying the Close method; Recordset objects are closed automatically when the variable that points to them goes out of scope. When you close a Recordset object, the memory that the object consumes is released to your application.

Note

Using Access VBA to create new Workspace, Database, User, Group, TableDef, and Relation objects is beyond the scope of this book. You can create these objects, with the exception of the Workspace object, much easier with Access's user interface. You also can create new TableDef objects with make-table queries or by using Jet SQL Data Definition Language statements.


Opening a New Recordset Object

You create a new Recordset object with the OpenRecordset method of Database, TableDef, and QueryDef objects. The general syntax of the OpenRecordset method has two forms:

							Set rsdName = dbName.OpenRecordset(str Source[, intType[,_
       intOptions[, intLockEdits]]])
     Set rsoName = objName. OpenRecordset([intType[, intOptions[, intLockEdits]]])

The first form, which is applicable only to Recordset objects created over Database objects, requires a value for the strSource argument. The value of the strSource argument can be the name of a TableDef object, or QueryDef object, or a Jet SQL statement. You also can use VBA's named arguments feature in the following statements:

							Set rsdName = OpenRecordset(Name:=str Source[, Type:=intType[,_
       Options:=intOptions[, LockEdits:=intLockEdits]]])
     Set rsoName = objName.OpenRecordset([Type: =intType[,_
       Options:=intOptions[, LockEdits:=intLockEdits]]])

Tables 27.1, 27.2, and 27.3 list values allowed for the intType, intOptions, and intLockEdits arguments for both of the preceding syntax examples. The values shown in the three tables are the names of predefined (intrinsic) global constants that are defined by the Jet 3.5 DAO. In earlier versions of Access, Access intrinsic global database constant names were uppercase and included underscore separators for readability, as in DB_OPEN_TABLE. Database intrinsic constants now are supplied by enumerations of the Jet 3.5 DAO and use the lowercase prefix db with intermediate capitalization to improve readability. A MethodArgumentEnum selection in the Class list of the Object Browser displays the names and values of applicable constants in the Members list (see Figure 27.9). In the case of the intOptions values listed in Table 27.2, you can combine the options you want with the VBA Or operator, as in dbDenyWrite Or dbDenyRead.

Figure 27.9. Some of the predefined (intrinsic) constants supplied by the Jet 3.5 DAO.


Table 27.1. Values for the intType Argument of the OpenRecordset Method Comparing DAO 3.5 and Access 2.0 Intrinsic Constants
DAO 3.5Access 2.0Description of Type
dbOpenTableDB_OPEN_TABLETable (default value for local TableDef source)
dbOpenDynasetDB_OPEN_DYNASETDynaset (default value for Database, QueryDef, Recordset, or an attached TableDef)
dbOpenSnapshotDB_OPEN_SNAPSHOTSnapshot (not updatable)
dbOpenForwardOnlyNot definedSimilar to a Snapshot, but you can move only forward through the Recordset (default for ODBCDirect Recordset objects).
dbOpenDynamicNot definedDynamic cursor (ODBCDirect Recordset objects only)

Table 27.2. Values for the intOptions Argument of the OpenRecordset Method Using DAO 3.5 and Access 2.0 Intrinsic Constants
DAO 3.5Access 2.0Description of Type
dbDenyWriteDB_DENYWRITEPrevents others from making changes to any records in the underlying table(s) while the Recordset is open.
dbDenyReadDB_DENYREADPrevents others from reading any records in the underlying table while the Recordset is open. This option, which applies to Table-type Recordset objects only, should be used for administrative purposes only in a multiuser environment.
dbReadOnlyDB_READONLYDoes not allow updates to records in the table. Read-only access increases the speed of some operations.
dbAppendOnlyDB_APPENDONLYAllows appending only new records. (Applies to Dynaset-type Recordset objects only.)
dbInconsistentDB_INCONSISTENTYou can update the one side of a one-to-many relationship. (Applies to Dynaset-type Recordset objects only.)
dbConsistentDB_CONSISTENTYou cannot update the one side of a one-to-many relationship, the default. (Applies to Dynaset-type Recordset objects only.)
dbForwardOnlyDB_FORWARDSCROLLCreates a Recordset object of the forward-scrolling-only Snapshot type.
dbSQLPassThroughNot definedSpecifies a SQL pass-through query against an ODBC database using Jet; returns a Snapshot-type Recordset.
dbSeeChangesNot definedGenerates a runtime error when the user attempts to change data that another user is currently editing (Dynaset-type Recordset only).
dbRunAsyncNot definedExecutes the query asynchronously, allowing the query to be canceled during execution (ODBCDirect only).
dbExecDirectNot definedRuns a query with no parameters directly, instead of creating a prepared statement (ODBCDirect only).

Table 27.3. Values for the intLockEditsArgument of the OpenRecordset Method of DAO 3.5
DAO 3.5Purpose of Option
dbReadOnlyDoes not allow updates to the Recordset.
dbPessimisticUses pessimistic locking (locks the edited page during editing).
dbOptimisticUses optimistic locking (locks the edited page only when applying the edits).
dbOptimisticValueUses optimistic locking based on row values (ODBCDirect only).
dbOptimisticBatchUses optimistic locking for batch updates (ODBCDirect only).

Note

There are many limitations on the use of constant values for the intOptions and intLockEdits arguments of the OpenRecordset method. For instance, you receive an error if you use the dbReadOnly constant in both of these arguments. The "Remarks" section of the help topic for the OpenRecordset method explains the conflicts in detail.


The following two sections show how to create two different types of Recordset objects.

A Recordset Object that Represents the Image of a Table. You can create the following two types of Recordset objects over a table, both of which create a virtual table in memory:

  • Recordset object of the Dynaset type created from the current Database object. To open a Dynaset-type Recordset object over the Orders table, add the PrivaterstCurrent AsRecordset variable declaration statement to the Declarations section of the module. Then use the following statement to assign the pointer, assuming that you have previously executed the Set dbCurrent = CurrentDB() statement:

    									Set rsdCurrent = dbCurrent.OpenRecordset("Orders", dbOpenDynaset)
    
  • A Recordset object of the Table type created from a TableDef object. To open a Table Recordset object over the Orders table, add the Private tdfCurrentAsTableDef variable declaration statement to the Declarations section of the module. Then use the following statements to assign the pointers:

    									Set tdfCurrent = dbCurrent.TableDefs("Orders")
    Set rstCurrent = tdfCurrent.OpenRecordset(dbOpenTable)
    

Figure 27.10 illustrates the creation of both of the preceding types of Recordset objects in the Debug Window.

Figure 27.10. Creating Recordset objects of the Dynaset and Table type in the Debug Window.


Moving to a Specific Record in a Recordset Object. Opening a Recordset of the Table type lets you quickly find a record in a table with the Seek method. This method is applicable only to Table-type Recordset objects whose underlying table contains an index on the field in which the value you want to find is located. To apply the Seek method, you first must specify the index name. The following example sets the record pointer to the record in the Orders table of Northwind.mdb with a value of 10833 in the OrderID field, the primary key of the table:

							Set dbCurrent = CurrentDB()
      Set tdfCurrent = dbCurrent.TableDefs("Orders")
      Set rstCurrent = tdfCurrent.OpenRecordset()
      rstCurrent.Index = "PrimaryKey"
      rstCurrent.Seek "=", 10833
      If rstCurrent.NoMatch Then
         'Record not found, display message box
      Else
        'Record found, add code to process the record here
      End If
						

Note

You can't enter conditional statements in the Debug Window, but you can test the preceding code by typing the entries up to and including the Seek line and then executing ? rstCurrent.NoMatch to determine whether the Seek method was successful in finding a matching record. The NoMatch property uses the Boolean data type. If False is returned, the record pointer rests on the matching record.


If the field in which you are Seeking the value is not the primary key field, you specify the field's name. The NoMatch property returns False if the value specified by the Seek expression is found; it returns True if a matching record is not found. Figure 27.11 shows typical entries to test the Seek method in the Debug Window. Test the Indexes collection of the TableDef object to verify that the index you specify exists. The Seek method allows the use of a variety of other operators, such as < or >=, in place of the = operator.

Figure 27.11. Applying the Seek method to Recordset objects of the Table type.


Tip

You cannot apply the Find... methods to a forward-scrolling-only Recordset object of the Snapshot type. The only method applicable to such objects is MoveNext.


You use the Find... methods to locate a specific record in Recordset objects of the Dynaset and Snapshot type. There are four Find... methods: FindFirst, FindNext, FindLast, and FindPrevious. Not surprisingly, each method does what its name indicates. The general syntax of the Find... methods is

      rsdName.Find{First|Next|Last|Previous} strCriteria

The single strCriteria argument of the Find... methods must be a valid SQL WHERE clause without the WHERE reserved word. As with the Seek method, the NoMatch property returns False if a match occurs. Figure 27.12 shows examples of the use of the four Find… methods.

Figure 27.12. Applying the Find methods to Recordset objects of the Dynaset or Snapshot type.


A Recordset that Emulates a QueryDef Object. You can substitute a valid Jet SQL statement for a table or query name as the value of the strSource property to create a Recordset object of the Dynaset or Snapshot type. You only can create such a Recordset over the Database object because more than one TableDef object may participate in the query. Such a Recordset is the equivalent of an "impersistent QueryDef" object (a QueryDef object that is not a Document object). Figure 27.13 shows you how to create a Recordset object by using a SQL statement in the Debug Window. You must add a Private strSQLAs String statement to the Declarations section of the module if the OptionExplicit statement has been executed. The entire strSQL = _ statement is

      strSQL = "SELECT * FROM Orders, [Order Details]
      WHERE [Order Details].OrderID = Orders.OrderID
      AND Orders.CustomerID = 'BERGS'"

If you need to manipulate a Recordset's records only temporarily, creating the "impersistent QueryDef" Recordset is faster than creating a legitimate, persistent QueryDef object.

Figure 27.13. Creating a Recordset object with a Jet SQL statement.


Defining a New QueryDef Object

You use the CreateQueryDef method to create a new, persistent QueryDef object and add it to the QueryDefs collection. One of the advantages of creating a QueryDef is that you can use the name you give the QueryDef in place of a table name in a Jet SQL statement. The name of the QueryDef must not duplicate the name of an existing QueryDef or TableDef object. The syntax for creating a new QueryDef object is

							Set qdfName = dbName.CreateQueryDef(str Name, strSQL)

Tip

You need to apply the MoveLast method before testing the value of the RecordCount property. If you omit the MoveLast method, you usually receive an erroneous RecordCount value (1). However, you can test whether any recorders were returned by testing with an If rstName. RecordCount Then ... End If structure.


QueryDef objects are what their object class name implies: the definition of a query. If strSQL's SQL statement represents an action query, you apply the Execute method to the QueryDef object to execute the query. You must create a Recordset over QueryDef objects that define select queries in order to read values in the query result set. Figure 27.14 illustrates how you create a new QueryDef object and open a Recordset object based on the QueryDef. You need to add Private qdfCurrent As QueryDef to the Declarations section of your code before you can execute the code shown in the Debug Window of Figure 27.14. When you execute a statement that includes the CreateQueryDef() method, the new QueryDef appears in the Queries page of the Database window. You can open a QueryDef created by Access VBA, as shown in Figure 27.15.

Figure 27.14. Creating a new QueryDef object and opening a Recordset over the QueryDef.


Figure 27.15. Opening a new QueryDef object created with Access VBA code.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.93.245