Avatar billede superraider Nybegynder
08. oktober 2006 - 22:44 Der 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
Avatar billede superraider Nybegynder
08. oktober 2006 - 22:45 #1
end function  ofc.
Avatar billede softspot Forsker
08. oktober 2006 - 22:50 #2
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

  FindName = navnet
end function

navn = FindName("tester")
Avatar billede superraider Nybegynder
08. oktober 2006 - 22:57 #3
hvorfor "dim navn" først så ?

og FilesInDB.close er vel ikke nødvendig?

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

Set Conn = Server.CreateObject("ADODB.Connection")
DSN = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("../db/borkforum.mdb")

hver gang.

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

Er der noget dumt i det?
Avatar billede superraider Nybegynder
08. oktober 2006 - 22:58 #4
dim Conn  før Function open()
Avatar billede softspot Forsker
09. oktober 2006 - 00:45 #5
"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. :)
Avatar billede superraider Nybegynder
09. oktober 2006 - 14:49 #6
smid et svar.


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.

men tak, gav lidt mere indblik i det
Avatar billede superraider Nybegynder
09. oktober 2006 - 14:54 #7
et spørgsmål lige til sidst.

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å.

håber du forstår sørgsmålet
Avatar billede softspot Forsker
09. oktober 2006 - 16:16 #8
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.
Avatar billede superraider Nybegynder
09. oktober 2006 - 16:31 #9
takker
Avatar billede softspot Forsker
09. oktober 2006 - 16:47 #10
Velbekomme og tak for point :)
Avatar billede superraider Nybegynder
09. oktober 2006 - 16:48 #11
set objConn = openDB()

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()
Avatar billede superraider Nybegynder
09. oktober 2006 - 16:51 #12
set ConnObj = openDB()
Microsoft VBScript runtime  error '800a000d'

Type mismatch: 'openDB'

/default.asp, line 25
Avatar billede superraider Nybegynder
09. oktober 2006 - 16:51 #13
ups min fejl den sidste der, havde ikke fået uploaded filen med functionen i
Avatar billede superraider Nybegynder
09. oktober 2006 - 17:10 #14
Set connObj = openDB()
SQL = "SELECT FORUM_USERGROUPS.USERGROUP_NAME, FORUM_USERGROUPS.USERGROUP_ID, FORUM_MEMBERS.MEMBER_ID, FORUM_MEMBERS.M_FIRSTNAME, FORUM_MEMBERS.M_LASTNAME FROM (FORUM_USERGROUP_USERS INNER JOIN FORUM_USERGROUPS ON FORUM_USERGROUP_USERS.USERGROUP_ID = FORUM_USERGROUPS.USERGROUP_ID) INNER JOIN FORUM_MEMBERS ON FORUM_USERGROUP_USERS.MEMBER_ID = FORUM_MEMBERS.MEMBER_ID WHERE (((FORUM_MEMBERS.M_NAME)='" & Session("Username") & "'))"
Userinfo = connObj.Execute(SQL)
Session("UserInfo") = Session("Username") & "," & Userinfo("M_FIRSTNAME") & "," & Userinfo("M_LASTNAME") & "," & Userinfo("MEMBER_ID") & "," & Userinfo("USERGROUP_ID") & "," & Userinfo("USERGROUP_NAME")
Userinfo.close  'line 10
Set Userinfo = Nothing

Microsoft VBScript runtime  error '800a01b6'

Object doesn't support this property or method: 'close'

/login-inc.asp, line 10
Avatar billede superraider Nybegynder
09. oktober 2006 - 17:12 #15
hehe ups igen, manglede et "set"
Avatar billede superraider Nybegynder
09. oktober 2006 - 17:18 #16
den her ka jeg ikke gennemskue:

ConnObj = openDB()
'SQL = "SELECT * FROM PICTURE_SHOWS"
SQL = "SELECT PICTURE_SHOWS.*, FORUM_MEMBERS.M_LASTNAME, FORUM_MEMBERS.M_FIRSTNAME FROM PICTURE_SHOWS INNER JOIN FORUM_MEMBERS ON PICTURE_SHOWS.SHOW_AUTHER = FORUM_MEMBERS.MEMBER_ID"

Set Albums = ConnObj.Execute(SQL)  'line 14

Microsoft VBScript runtime  error '800a01a8'

Object required: 'Provider=MSDASQL.1;E'

/albums.asp, line 14
Avatar billede superraider Nybegynder
09. oktober 2006 - 17:22 #17
hhaa, jeg trænger til at sove :)
Avatar billede softspot Forsker
09. oktober 2006 - 17:43 #18
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 :)
Avatar billede superraider Nybegynder
09. oktober 2006 - 19:28 #19
så du synes ikke der er meget dialog over den :P  jep fandt fejlen :) manglede endnu et "set"
Avatar billede softspot Forsker
09. oktober 2006 - 20:08 #20
OK, godt ;-)

Nej, jeg opfatter en envejskommunikation som en monolog - dialog er når to eller flere snakker sammen... nå, men lad nu det ligge :D
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester