08. oktober 2006 - 22:44Der er
19 kommentarer og 1 løsning
Rekursive kald i asp.
Kan man lave en function som denne. (har ikke lige taget databaseforbindelsen med.) dim navn Function FindName(Name) Set FilesInDB = conn.Execute("SELECT FILNAVN FROM PICTURES WHERE FILNAVN = '" & Name & "'") if FilesInDB.BOF and FilesInDB.EOF then 'den var der ikk, brug den her. navn = name else 'den var der allerede, prøv nyt navn. FindName("a" & Name) end if
Ja, men du bør undgå at tildele globale variable værdier fra funktioner, hvis det kan undgås...
dim navn Function FindName(Name) dim navnet, FilesInDB, FileDoesntExists
Set FilesInDB = conn.Execute("SELECT FILNAVN FROM PICTURES WHERE FILNAVN = '" & Name & "'") FileDoesntExists = (FilesInDB.BOF and FilesInDB.EOF) FilesInDB.close
if FileDoesntExists then 'den var der ikk, brug den her. navnet = Name else 'den var der allerede, prøv nyt navn. navnet = FindName("a" & Name) end if
Den måde jeg har det på, er at jeg har åbnet database forbindelsen i starten af documented, og lukker den igen i slutningen, istedet for at skulle diffinere
sådan her. Function open() Set Conn = Server.CreateObject("ADODB.Connection") ' Husk at angive den rigtige sti til din database DSN = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("../db/borkforum.mdb") ' Åben databaseforbindelsen Conn.Open DSN End Function Function close() Conn.Close Set Conn = Nothing End Function
"hvorfor "dim navn" først så ?" >> nu er det jo svært at vide hvad du skulle bruge navnet til, så jeg kunne jo ikke bare fjerne den. Desuden illustrerer det bare hvordan man kan holde funktions-lokale og globale variabel adskilt.
"og FilesInDB.close er vel ikke nødvendig?" >> Det er altid en god idé at rydde op efter sig, specielt når man har med sparsomme eller dyre resurser som databaser at gøre, så derfor vil jeg sige, luk recordsets og i særdeleshed connections (den sidste er nok mere vigtig), så er risikoen for at slipper op mindre :)
Det er også en fin idé at åbne sin connection én gang og så genbruge den, men specielt i rekursioner, som genbruger en connection til at forespørge i databasen, mener jeg det er vigtigt, at få lukket sine recordsets så hurtigt som muligt (inden du laver en ny rekursion). Rent faktisk vil jeg endda mene at du bør sætte FilesInDB til nothing umiddelbart efter close-kommandoen, så objektet bliver fjernet fra hukommelsen inden næste rekursion.
Dvs. det hele kunne se således ud:
dim navn, Conn
Function openDB() Set Conn = Server.CreateObject("ADODB.Connection") ' Husk at angive den rigtige sti til din database DSN = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("../db/borkforum.mdb") ' Åben databaseforbindelsen Conn.Open DSN End Function
Function closeDB() Conn.Close Set Conn = Nothing End Function
Function FindName(Name) dim navnet, FilesInDB, FileDoesntExists
Set FilesInDB = conn.Execute("SELECT FILNAVN FROM PICTURES WHERE FILNAVN = '" & Name & "'") FileDoesntExists = (FilesInDB.BOF and FilesInDB.EOF) FilesInDB.close Set FilesInDB = Nothing
if FileDoesntExists then 'den var der ikk, brug den her. navnet = Name else 'den var der allerede, prøv nyt navn. navnet = FindName("a" & Name) end if
FindName = navnet end function
call openDB() navn = FindName("tester") call closeDB()
Jeg er måske endda tilbøjelig til at ville skabe forbindelsen inde i OpenDB og returnere den til den kaldende part og så føre den med videre ned i FindName. Det ville så give en ekstra parameter, som skulle føres med i hver rekursion (og det vil du sikkert ikke være med til ;-))... men så ville indpakningen være endnu bedre - efter min mening. :)
jeg ka godt se din pointe, og normalt lukker jeg også mine database forbindelser når jeg er færdig med at bruge den. Har bare ikke lige tænkt at jeg også skulle lukke alle mine recordsets.
Hvis jeg har bygget mit strugtur op på følgene måde. top-inc.asp | bund-inc.asp
og så for alle mine side includer dem i top og bund.
hvad er best, at kalde openDB() i top.inc.asp og lukke den igen i bund-inc.asp. så er den altid åben når jeg skal bruge den, og bliver altid lukket igen. (også selvom jeg nødvendig vis ikke brugte den på en af siderne) eller at åbne og lukke den måske 5 gange ned over den samme side.(i tilfælde af at jeg includer nogle sider på en side som også bruge en forbindelse, hvor jeg åbner og lukker den i også.
Havde dit spørgsmål drejet sig om .NET, så havde mit svar entydigt været åben forbindelsen 5 gange og så tæt på det sted hvor du har brug for den, som muligt og luk den så hurtigt efter som muligt. Det er dog en anden sag når vi snakker ASP 3.0, da der, såvidt jeg ved, ikke er nogen effektiv form for connection-pooling.
Derfor er modellen en lille smule anderledes i ASP 3.0, idet jeg vil sige: åben forbindelsen første gang du får brug for den og luk den altid til sidst - hvis den har været åbnet... MEN GEM DEN FOR GUDS SKYLD IKKE I APPLICATION ELLER SESSION! :)
I denne model kan du fint bruge at åbningen af forbindelsen er pakket ind i en funktion, da du så bare skal kalde den funktion for at få en åben forbindelse og ikke bekymre dig om hvorvidt den er åben i forvejen eller ej...
Det kunne se nogenlunde således ud:
' Erklær forbindelsesobjektet globalt, så funktionerne nedenfor har ' noget at arbejde med. ' VIGTIGT! Denne variabel må aldrig refereres andre steder fra!! dim conn set conn = nothing
' Åbner (hvis nødvendigt) en connection og returnerer denne ' Der arbejdes med et globalt connection-objekt, som KUN ' åbnes fra denne funktion... function openDB() dim strConn strConn = "...dine connection-settings..."
' opretter et nyt forbindelsesobjekt, hvis det ikke er oprettet i forvejen... if conn is nothing then set conn = Server.CreateObject("ADODB.Connection") conn.open(strConn) end if
' åbner forbindelsen, hvis den er lukket... if conn.state = 0 then conn.open(strConn) end if
set openDB = conn end function
' Lukker forbindelsen til databasen, hvis den ikke allerede er lukket... sub closeDB() if not conn is nothing then if conn.state <> 0 then conn.close end if set conn = nothing end if end sub
Disse funktioner (som i øvrigt er helt utestet) kan du placere i en includefil som du inkluderer på alle sider (eller de sider som har behov for en forbindelse) og så når du har brug for en forbindelse kan du få en connection ved at kalde openDB, således:
set objConn = openDB() set rs = objConn.Execute("SELECT * FROM tabel") do while not rs.eof ' ...gør noget med denne record... rs.movenext loop rs.close
Dette mønster gentager du bare hver gang du skal lave et eller andet med databasen. Bemærk at jeg ikke lukker forbindelsen når jeg er færdig (da dette jo bliver gjort i din bund-include). Bemærk også at jeg lukker recordsettet når jeg er færdig med at bruge det (om ikke for andet, så for en god ordens skyld :)).
I din bund-include kalder du så bare rutinen closeDB for at lukke databasen (uanset om den har været åbnet eller ej, for rutinen kontrollerer selv om forbindelsen skal lukkes eller ej). Skulle du komme til at lukke forbindelsen ved en fejl et eller andet sted, så er det heller ikke en katastrofe, da openDB jo sørger for at åbne forbindelsen, hvis den er lukket... du opnår højst en ringere performance.
er det ligemeget hvad jeg sætter det objectnavn til "objConn"? og kan jeg kalde den det ene det enested og noget andet det andet sted, og stadig lukkes de alle til sidst med closeDB()
09/10-2006 16:48:29 >> ja, du kan kalde forbindelsesobjektet lige hvad du vil i den lokale kontekst hvor du skal bruge den, da det bare er en ny reference til det samme forbindelsesobjekt. VBScript skulle gerne sørge for at nedlægge denne reference, når konteksten nedlægges - f.eks. inde i en funktion, der jo går ud af kontekst (også kaldet "scope") når den afsluttes.
Er der i øvrigt nogle åbne spørgsmål i din seneste monolog? Jeg kan ikke helt gennemskue om du fandt en løsning på den sidste kommentar :)
Nej, jeg opfatter en envejskommunikation som en monolog - dialog er når to eller flere snakker sammen... nå, men lad nu det ligge :D
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.