ASPNL logo (1 kb)
zaterdag 17 mei 2008




Microsoft MVP

.NET Codewise Community
<< vorige | overzicht | volgende >>

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) 'Tussentijds record ingevoegd

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) 'Tussentijds record ingevoegd

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)

<< vorige | ^ naar boven | overzicht | volgende >>
copyright 2000-2007 ASPNL