Autonummerveld opvragen met een recordset
Door Ken Schaefer
9 juli 2001
Wat in dit artikel beschreven staat, is niet de beste/snelste manier om de waarde van een
autonummerveld op te vragen. De snelste manier met Acces en ASP/ADO vind je
hier.
Als je nog steeds geïnteresseerd bent in het opvragen van een autonummerveld met gebruik van
ASP en het ADO Recordset Object lees dan door.
De uitdaging:
Als je de waarde van een autonummerveld opvraagt na het invoegen van een nieuw record met gebruik
van de AddNew methode van het Recordset Object, moet dan (eerst) de
MoveLast methode van het Recordset object worden aangeroepen?
Hangt deze vereiste (als dat al zo is) ook af van het type cursor dat gebruikt wordt?
Ken's hypothese:
Als je een ForwardOnly, Static of Keyset cursor gebruikt dan zal de MoveLast methode
niets doen, aangezien de cursor dan al hoort bij het laatste record (namelijk het record dat net gecreëerd is).
Als je een Dynamic cursor gebruikt dan kan de MoveLast methode onbedoelde resultaten
opleveren, omdat een andere gebruiker een record ingevoegd kan hebben nadat je de Update
methode hebt aangeroepen maar voordat je de waarde van het autonummer veld hebt opgevraagd.
Test 1 - De code:
We beginnen met een simpele test. Ik gebruik een bestaande database. Ik heb een nieuwe tabel gecreëerd,
genaamd "TestTable" met 2 velden:
- TableID (autonummer, primaire sleutel)
- SomeData (tekst veld, lengte 50, vereist)
Onze eerste test is met een Open Forward cursor (en zonder MoveLast) en begint
met de volgende code:
<%
Set objRS = Server.CreateObject("ADODB.Recordset")
With objRS
.CursorType = adOpenForwardOnly
.LockType = adLockOptimistic
.ActiveConnection = Application("adOpenStatic_ConnectionString")
End With
objRS.Open "TestTable",,,,adCmdTable
objRS.AddNew
objRS("Somedata") = "Data voor test nummer 1"
objRS.Update
intID = objRS("TableID")
objRS.Close
Set objRS = Nothing
Response.Write(intID)
%>
leverde de waarde 1 op(zoals verwacht).
Conclusie:Het blijkt dat de MoveLast methode niet vereist is om het
autonummerveld ID op te vragen.
Test 2 - Static Cursors?
Op een mailinglist over databases, rees nu de vraag of je met een Static cursor wel de
MoveLast methode moet gebruiken. Ik heb de test nog een keer gedaan, waarbij ik dezelfde
code als hierboven heb gebruikt, maar ditmaal met een adOpenStatic cursor. Het resultaat van het
Response.Write statement was 2 (zoals verwacht).
Conclusie: Het gebruik van een adOpenStatic cursor geeft geen andere resultaten dan wanneer
je een adOpenForwardOnly cursor gebruikt zonder MoveLast.
Test 3 – Wat gebeurt er als we MoveLast gebruiken?
Teruggaand naar het gebruik van een adOpenForwardOnly cursor voeg ik de MoveLast
methode als volgt in:
<%
Set objRS = Server.CreateObject("ADODB.Recordset")
With objRS
.CursorType = adOpenForwardOnly
.LockType = adLockOptimistic
.ActiveConnection = Application("adOpenStatic_ConnectionString")
End With
objRS.Open "TestTable",,,,adCmdTable
objRS.AddNew
objRS("Somedata") = "Data voor test nummer 3"
objRS.Update
objRS.MoveLast
intID = objRS("TableID")
objRS.Close
Set objRS = Nothing
Response.Write(intID)
%>
Het Response.Write statement leverde de waarde 3 op (zoals verwacht).
Conclusie: Het gebruik van MoveLast met een adOpenForwardOnly cursor
verandert het eindresultaat niet. Aangezien het oproepen van de MoveLast methode met
zich meebrengt dat een extra functie aangeroepen moet worden, die geen voordeel oplevert, wordt er aanbevolen
MoveLast niet aan te roepen.
Test 4 – Maakt een tussentijdse Insert een verschil?
Volgens mijn hypothese kan dat – maar alleen als je een Dynamic cursor gebruikt.
We beginnen met het gebruik van de onderstaande code. Deze gebruikt de adOpenForwardOnly cursor en
de MoveLast methode. In deze test voegen we een record in, roepen de
Update methode aan, voegen het volgende record in en dan proberen we de
oorspronkelijke ID op te vragen. Het eerste record dat we tussenvoegen zou ID 4 moeten hebben, het volgende
record (tussengevoegd via de SQL string) zou de waarde 5 moeten hebben.
<%
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("adOpenStatic_ConectionString")
Set objRS = Server.CreateObject("ADODB.Recordset")
With objRS
.Cursorype = adOpenForwardOnly
.LockType = adLockOptimistic
.ActiveConnection = objConn
End With
objRS.Open "TestTable",,,,adCmdTable
objRS.AddNew
objRS("Somedata") = "Data voor test nummer 4
strSQL = "INSERT INTO TestTable(SomeData)"
strSQL = strSQL & VALUES('Data voor test nummer 4')"
objConn.Execute(strSQL)
objRS.MoveLast
intID = objRS("TableID")
objRS.Close
Set objRS = Nothing
objConn.Close
SetobjConn = Nothing
Response.Write(intID)
%>
Het Response.Write statement leverde de verwachte ID waarde op (namelijk 4).
Conclusie: De MoveLast methode doet niets als een record tussentijds is
ingevoegd en een cursor is gebruikt, die niet toestaat dat de gebruiker veranderingen ziet die door andere gebruikers
zijn verricht.
Test 5 – Wat gebeurt er als we een Dynamic cursor gebruiken?
We zullen de code gebruiken zoals in het voorbeeld hiervoor. We veranderen alleen de cursor naar
adOpenDynamic. Deze cursor staat de gebruiker toe veranderingen te zien die door andere gebruikers zijn gedaan.
Volgens mijn hypothese moeten we de Update methode aanroepen (een record invoegen
met ID 6), het tussentijdse record invoegen (met ID 7), de MoveLast methode aanroepen
(wat de cursor zal verplaatsen naar ID 7), en de ID waarde opvragen.
Het Response.Write statement zou 7 als waarde naar het scherm moeten schrijven.
<%
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("adOpenStatic_ConectionString")
Set objRS = Server.CreateObject("ADODB.Recordset")
With objRS
.Cursorype = adOpenDynamic
.LockType = adLockOptimistic
.ActiveConnection = objConn
End With
objRS.Open "TestTable",,,,adCmdTable
objRS.AddNew
objRS("Somedata") = "Data voor test nummer 5
strSQL = "INSERT INTO TestTable(SomeData)"
strSQL = strSQL & VALUES('Data voor test nummer 5')"
objConn.Execute(strSQL)
objRS.MoveLast
intID = objRS("TableID")
objRS.Close
Set objRS = Nothing
objConn.Close
SetobjConn = Nothing
Response.Write(intID)
%>
Dit werkt niet zoals ik had verwacht. Het Response.Write statement leverde waarde 6 op,
niet 7. Ik ben er net achter dat de OLEDB.4.0 Provider de adOpenDynamic cursors niet ondersteunt. Bij pogingen
om een adOpenDynamic cursor te openen, komt deze terug als een Keyset cursor. Dit kan zijn waarom het
bovenstaande niet werkt.
Hoe dan ook, mijn conclusie van het bovenstaande is dat:
-
Bij pogingen om de waarde van een autonummer veld op te vragen nadat een record is ingevoegd, maakt het niet uit
welke cursor je gebruikt (wat betreft het uiteindelijke resultaat). Aangezien de adOpenForward cursor het minst kostbare
is, zou je die moeten gebruiken.
-
De MoveLast methode is niet vereist – tegelijkertijd echter geeft het geen ongunstige
resultaten. Aangezien bij het aanroepen van de MoveLast methode een extra functie nodig
is, zou je die moeten vermijden.
Elk commentaar op het bovenstaande is van harte welkom.
Getest op Win2k Professional, Access 97 database, Microsoft.JET.OLEDB.4.0 Provider, MDAC v2.5
© Ken Schaefer
(vertaling copyright ASPNL)
|