Trying to measure a website performance I created a simple logging sub to see what parts are slow during the execution of a classic asp page.
sub log(logText)
dim fs, f
set fs = Server.CreateObject("Scripting.FileSystemObject")
set f = fs.OpenTextFile("log.txt", 8, true)
f.WriteLine(now() & " - " & logText)
f.Close
set f = Nothing
set fs = Nothing
end sub
log "Loading client countries"
set myR = Server.CreateObject("ADODB.RecordSet")
myR.ActiveConnection = aConnection
myR.CursorLocation=2
myR.CursorType=3
myR.LockType=2
myR.Source = "SELECT * FROM CC ORDER BY ccName ASC"
log "Opening db connection"
myR.open()
log "Opened db connection"
Here are the results (only showing the time part):
...
11:13:01 - Loading client countries
11:13:06 - Opening db connection
11:13:06 - Opened db connection
...
Creating the ADODBRecordSet and setting a few properties takes about 5 seconds. This does not always happen, sometimes the code is executed fast, but usually when I reload the page
after a few minutes the loading times are more or less the same as the example's. Could this really be a server/resources issue or should I consider rewriting the code? (My best option would be to write this in C#, but I have to study this code first before moving forward anyway).
Update: I added more code after receiving 1st comment to present a few more code. Explanation: The code creates a combobox (selection menu) with the retrieved countries (it continues where the previous piece of code stopped).
if not myR.eof then
clientCountries = myR.getrows
send("<option value='0'>Select country</option>")
log "Creating combobox options"
for i = 0 to ubound(clientCountries, 2)
if cstr(session("clientCountry")) <> "" then
if cstr(clientCountries(1, i)) = cstr(session("clientCountry")) then
isSelected = "selected" else isSelected = ""
end if
end if
if cstr(session("clientCountry")) = "" then
if cstr(clientCountries(1, i)) = "23" then
isSelected = "selected"
else
isSelected = ""
end if
end if
optionString = ""
optionString = clientCountries(2, i)
send("<option value='" & clientCountries(1, i) & "' " & isSelected & ">" & convertToProperCase(optionString) & "</option>")
next
log "Created combobox options"
end if
myR.Close
myR.ActiveConnection.close
myR.ActiveConnection = nothing
set myR = nothing
log "Loaded client countries"
The next two log entries are as follows:
11:13:06 - Creating combobox options
11:13:06 - Created combobox options
...
So far, the SELECT query as the rest of the page (2 or 3 queries more) is executed within the next second more or less. The only part slowing the page down is what you can see in the first part of the log. I'm not sure if I can profile the SQLServer, because I only have cPanel access. This is the only way I know of, unless there's something else I could have a look at.
First, Check your connection string, I've experienced slower times with certain providers. The best provider I've found for classic asp is sqloledb
Second, I would close my SQL object before I did the For statement on the GetRows() array. You don't want to keep that open if you don't need to.
Third, I'd use stored procedures. You'll get a performance improvement by saving on compile time.
Fourth, I would avoid doing a SELECT * statement at all cost, instead I would return ONLY the columns I need. (Your code looks like it only needs 2 columns)
Fifth, I would build indexes on the tables taking longer than expected.
If this doesn't resolve the issue, I would consider other languages/solutions. Not sure what the dataset looks like, so can't say if a flat-file database should be considered or not.
Also, try this for a recordset instead and see what happens:
Set myR = Server.CreateObject("Adodb.Recordset")
myR.Open "SELECT * FROM CC ORDER BY ccName ASC", aConnection
If myR.RecordCount > 0 Then clientCountries = myR.GetRows()
myR.Close
Set myR = Nothing
If IsArray(myR) Then
For ....
Related
I'm using Pervasive 9.2 and would like to somehow convert the vbscript into pervasives RIFL language. I want to execute the code during a Process where the f(x) component is executed to run the code. As far as the Path to the xml data, I'll be using a Macro defining where the source data is and another to save the file as well.
Here is the vbscript code below:
Set xml = CreateObject("Microsoft.XMLDOM")
xml.async = False
count_var = 1
If xml.Load("c:\folder1\test.xml") Then
For Each accounts In xml.SelectNodes("//Accounts")
For Each account In Accounts.SelectNodes("./Account")
If count_var > 1 Then
Set accountEnum = xml.createNode(1, "Account" & count_var, "")
For Each child In Account.childNodes
accountEnum.appendChild(child.cloneNode(TRUE))
Next
Accounts.replaceChild accountEnum, Account
xml.save("c:\folder1\test.xml")
else
Set accountEnum = xml.createNode(1, "Account" & count_var, "")
For Each child In Account.childNodes
accountEnum.appendChild(child.cloneNode(TRUE))
Next
Accounts.replaceChild accountEnum, Account
xml.save("c:\folder1\test.xml")
End If
count_var = count_var + 1
Next
count_var = 1
Next
End If
Set node = Nothing
Set xml = Nothing
ParseXMLFile(filepath)
documentation here
http://docs.pervasive.com/products/integration/di/rifl/wwhelp/wwhimpl/common/html/wwhelp.htm#href=ParseXMLFile_Function.html&single=true
this will return a DOMDocument Object Type
documentation here
http://docs.pervasive.com/products/integration/di/rifl/wwhelp/wwhimpl/common/html/wwhelp.htm#href=DOMDocument_Object_Type.html&single=true
hope this helps
I'm trying to add records to an exisiting table called "Topics" (section as of "For Each SelectedTopic In SelectedTopicsCtl.ItemsSelected" in the code below).
When executing the code i always get "Run-time error '3022': The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. So it goes wrong at the creation of the Autonumber in the field "ID" (= the only field that is indexed - no duplicates).
When debugging, line "TopicRecord.Update" in the code below is highlighted.
I have read several posts on this topic on this forum and on other forums but still cannot get this to work - i must be overlooking something....
Private Sub Copy_Click()
Dim JournalEntrySourceRecord, JournalEntryDestinationRecord, TopicRecord As Recordset
Dim JournalEntryToCopyFromCtl, JournalEntryToCopyToCtl, JournalEntryDateCreatedCtl, SelectedTopicsCtl As Control
Dim Counter, intI As Integer
Dim SelectedTopic, varItm As Variant
Set JournalEntryToCopyFromCtl = Forms![Copy Journal Entry]!JournalEntryToCopyFrom
Set JournalEntryToCopyToCtl = Forms![Copy Journal Entry]!JournalEntryToCopyTo
Set JournalEntryDateCreatedCtl = Forms![Copy Journal Entry]!JournalEntryDateCreated
Set JournalEntrySourceRecord = CurrentDb.OpenRecordset("Select * from JournalEntries where ID=" & JournalEntryToCopyFromCtl.Value)
Set JournalEntryDestinationRecord = CurrentDb.OpenRecordset("Select * from JournalEntries where ID=" & JournalEntryToCopyToCtl.Value)
Set SelectedTopicsCtl = Forms![Copy Journal Entry]!TopicsToCopy
Set TopicRecord = CurrentDb.OpenRecordset("Topics", dbOpenDynaset, dbSeeChanges)
With JournalEntryDestinationRecord
.Edit
.Fields("InitiativeID") = JournalEntrySourceRecord.Fields("InitiativeID")
.Fields("DateCreated") = JournalEntryDateCreatedCtl.Value
.Fields("Comment") = JournalEntrySourceRecord.Fields("Comment")
.Fields("Active") = "True"
.Fields("InternalOnly") = JournalEntrySourceRecord.Fields("InternalOnly")
.Fields("Confidential") = JournalEntrySourceRecord.Fields("Confidential")
.Update
.Close
End With
JournalEntrySourceRecord.Close
Set JournalEntrySourceRecord = Nothing
Set JournalEntryDestinationRecord = Nothing
For Each SelectedTopic In SelectedTopicsCtl.ItemsSelected
TopicRecord.AddNew
For Counter = 3 To SelectedTopicsCtl.ColumnCount - 1
TopicRecord.Fields(Counter) = SelectedTopicsCtl.Column(Counter, SelectedTopic)
Next Counter
TopicRecord.Fields("JournalEntryID") = JournalEntryToCopyToCtl.Value
TopicRecord.Fields("DateCreated") = JournalEntryDateCreatedCtl.Value
TopicRecord.Update
Next SelectedTopic
TopicRecord.Close
Set TopicRecord = Nothing
End Sub
First, your Dims won't work as you expect. Use:
Dim JournalEntrySourceRecord As Recordset
Dim JournalEntryDestinationRecord As Recordset
Dim TopicRecord As Recordset
Second, it looks like you get your ID included here:
TopicRecord.Fields(Counter)
or Topic is a query that includes it somehow. Try to specify the fields specifically and/or debug like this:
For Counter = 3 To SelectedTopicsCtl.ColumnCount - 1
TopicRecord.Fields(Counter).Value = SelectedTopicsCtl.Column(Counter, SelectedTopic)
Debug.Print Counter, TopicRecord.Fields(Counter).Name
Next Counter
I've got a classic ASP application that contacts a database and receives a valid response but then crashes with
Error Number 9: Subscript out of range
after exiting the IF block the db call is made in. What's odd is that the same code is currently working in production. As far as I can tell they're configured identically (but I suspect there's a subtle difference that's causing this issue) and have identical code bases.
What I want to know is:
Where is this array that I'm supposedly attempting to reach a non-existent index of? I don't see it and the error gives no line number. Is there a chance something is not working correctly in the adodb library?
Perhaps this is a common problem having to do with a certain patch and my particular db connection library? Have you had a similar experience?
How do I troubleshoot a problem that doesn't immediately present itself? Should I just start putting troubleshooting statements in the library?
Explanation of what's happening in the code: When the cookie "click" is received err.number is 0. When the cookie "bang" is received the err.number is 9. It then crashes with that error at the end of the IF block.
<%#Language="VBSCRIPT"%>
<% Server.ScriptTimeout = 150 %>
<%
On Error resume Next
%>
<!--#include file="adovbs.inc"-->
<!--#INCLUDE FILE="DBConn.asp"-->
<!--#INCLUDE FILE="ErrorHandler.asp"-->
<%
'Application Timeout Warning
sessionTimeout = 20
advanceWarning = 5
jsTimeout = (sessionTimeout - advanceWarning) * 60000
'If the users session has expired
If Session("USERNAME") = "" or Session("USERNAME") = NULL Then
Response.Redirect("default.asp")
End If
'If the user has just changed their password. Prompt them that it was successfully changed
If Request("changePasswd") = "true" Then
Response.Write("<script language='Javascript'>alert('Your Password Has been Successfully Changed!');</script>")
End If
Dim connection, cmd, objRS, latestDate, lastDateJPMC, firstDateJPMC, lastDateWACH, firstDateWACH, lastDateWFB, firstDateWFB, accountCount
Function calConvertDate(theDate)
Dim yr, mn, dy, dtSplit
dtSplit = Split(theDate,"/")
yr = dtSplit(2)
mn = dtSplit(0)
dy = dtSplit(1)
if Len(mn) = 1 then mn = "0" & mn
if Len(dy) = 1 then dy = "0" & dy
calConvertDate = "[" & yr & "," & mn & "]"
End Function
set connection = Server.CreateObject("adodb.connection")
connection.Open DBConn
connection.CommandTimeout = 60
set connection = Server.CreateObject("adodb.connection")
connection.Open DBConn
connection.CommandTimeout = 60
'Get Earliest & Latest Date in Database
If Err.Number = 0 Then
Response.Cookies("CLICK")=Err.number
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
Set .ActiveConnection = connection
.CommandText = "CIRS_Admin.spGetLatestDate"
.CommandType = adCmdStoredProc
set objRS = .Execute
End With
latestDate = calConvertDate(objRS("latestDate"))
Response.Cookies("latestdate")=objRS("latestDate")
objRS.Close
Set objRS = Nothing
Response.Cookies("BANG")=Err.number
End If
To debug, please add a statement like
Response.Write (objRS("latestDate"))
before the line
latestDate = calConvertDate(objRS("latestDate"))
so you can see if (for example) the date returned from the server has "-" as separator instead of "/" or if an empty value is returned.
After understanding what is causing the problem you can solve it
1.Where is this array that I'm supposedly attempting to reach a non-existent index of? I don't see it and the error gives no line number. Is there a chance something is not working correctly in the adodb library?
This is your array:
yr = dtSplit(2)
mn = dtSplit(0)
dy = dtSplit(1)
What's odd is that the same code is currently working in production. As far as I can tell they're configured identically (but I suspect there's a subtle difference that's causing this issue) and have identical code bases.
May be you have different regional settings?
I strongly suggest to you use better error handling.
Internal Server Error 500 w/ IIS Log
I have been a longtime lurker of stackoverflow and have now decided to join. I am trying to pull a list of every Functional Location out of SAP using BAPI. When I run this code it returns with an empty table. I dont have very much experiance with BAPI and I am trying to teach myself. Can someone please help with what im missing to make this work.
Thanks,
See code bellow:
Dim sapFunc As New SAPFunctionsOCX.SAPFunctions
Dim objServer = sapFunc.Connection
objServer.Client = "101"
objServer.User = "MyUserName"
objServer.Ticket = "MyKey"
objServer.system = "PEC"
objServer.MessageServer = "MyMessagerServer"
objServer.GroupName = "PUBLIC"
If objServer.logon(0, True) <> True Then
MsgBox("Key Rejected")
Exit Sub
End If
Dim objRfcFunc As SAPFunctionsOCX.Function
objRfcFunc = sapFunc.Add("BAPI_FUNCLOC_GETLIST")
'System.Console.Write(objRfcFunc.Description)
If objRfcFunc.Call = False Then
MsgBox("Error occured - " & objRfcFunc.Exception)
Exit Sub
End If
Dim tab = objRfcFunc.Tables("FUNCLOC_LIST")
System.Console.WriteLine("Input start:")
For I = 1 To tab.RowCount
For j = 1 To tab.ColumnCount
System.Console.Write(tab.ColumnName(j) + ":")
System.Console.WriteLine(tab.Cell(I, j))
Next
Next
System.Console.WriteLine("Input end.")
I don't intend for this to be an answer, but if it helps then that's good. If it doesn't, I'll delete it.
With objRfcFunc.tables("funcloc_ra")
If .RowCount < 1 Then .Rows.Add
.cell(1, 1) = "I"
.cell(1, 2) = "EQ"
.cell(1, 3) = "Your Func Loc"
End With
Do this after setting objRfcFunc and before calling it. The call will use these parameters.
I means to Include, EQ means you want to find items equal to the value in low.
I would extremely appreciate if anyone can suggest a solution for this.
I have a simple function that is is expecting for a browser to be opened on a page containing a web list that each value of it represents an account. When an account is selected it's products (if any) are displayed.
The functions goal is to retrieve an index of an account with products (the first to be found) or -1 if there are none.
The problem, which I can't figure out what is causing it, is that the function will return the correct result when I'm debugging it - meaning running the code step by step using F10, but will return a wrong result if I'll run regularly (F5). This behavior is consistent and the function retrieves the same result each time for each type of runs, meaning it's not a bug that just makes the function return a random answer.
This is the function:
' #return: a random account index with products if one exists
' otherwise returns -1
Public Function getRandomAccountWithProducts()
On Error Resume Next
Set Page1 = Browser("micclass:=browser").Page("micclass:=Page")
Set br = Browser("micclass:=Browser")
originalURL = br.GetROProperty("URL")
br.Navigate Environment.Value("SOME URL") & "REST OF URL"
br.Sync
Page1.WebList("name:=accountId").Select "#1"
br.Sync
' Display only products
Page1.WebRadioGroup("name:=name0").Click
Page1.WebList("name:=name1").Select "Display None"
Page1.WebList("name:=name2").Select "Display None"
Page1.WebButton("value:=Apply","visible:=True").Click
' Init
numOfAccounts = Page1.WebList("name:=accountId").GetROProperty("items count") - 1
If numOfAccounts < 1 Then
getRandomAccountWithProducts = -1
Reporter.ReportEvent micFail, "Number of accounts","There are no accounts. No account with products exists"
Exit Function
End If
hasProducts = false
accountIndex = 1
' Get account with products
While ((Not hasProducts) AND (accountIndex =< numOfAccounts))
' Return account if has products
If Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5) Then
hasProducts = true
End If
If (Not hasProducts) Then
accountIndex = accountIndex + 1
Page1.WebList("name:=accountId").Select "#" & accountIndex
End If
Wend
br.Navigate originalURL
Set Page1= Nothing
Set br = Nothing
' If no account has products, report and exit, else return selected account index
If Not hasProducts Then
Reporter.ReportEvent micFail,"Accounts","No account has products."
getRandomAccountWithProducts = -1
Else
getRandomAccountWithProducts = accountIndex
End If
If Err<>0 Then
errorMessage = "Error number: " & Err.Number & vbNewLine & "Error description: " & Err.Description & vbNewLine & "Error source: " & Err.Source
Reporter.ReportEvent micFail,"Run Time Error",errorMessage
Err.Clear
End If
On Error GoTo 0
End Function
I'm running on Pentium 4, 3.2 GHZ, 2 GB RAM, Win XP, SP 3,IE 7, QTP 10.0 Build 513
Thanks!
Have you considered using the all items property?
AllItems = Page1.WebList("name:=accountId").GetROProperty("all items")
SplitItems = Split(AllItems, ";")
Found = False
For i = 0 To UBound(AllItems)
If AllItems(i) = "<product>" Then
Found = True
Exit For
End If
Next
Solution was found thanks to Jonty,
The problem was in the following section:
' Get account with products
While ((Not hasProducts) AND (accountIndex =< numOfAccounts))
' Return account if has products
If Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5) Then
hasProducts = true
End If
If (Not hasProducts) Then
accountIndex = accountIndex + 1
Page1.WebList("name:=accountId").Select "#" & accountIndex
End If
Wend
The first time entered to the loop, the account really didn't have any products, so obviously none was recognized. So accountIndex was increased by one and the corresponding account was selected in the web list.
No here lies the problem. The select method caused a refresh in the page and the condition Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5)
was evaluated before the web list was loaded thus, returning false.
I considered that option, but I thought (wrongly apparently) that the Exist(5) should do the trick, but it seems that it works differently than expected.
Thanks,
Alon