Result is always zero - asp-classic

When perform this piece of code on my webserver the result is always 0 (ZERO)
Can anyone give a hunch on this problem (solution even better :-D )
Dim MyTotalPages
Dim Recordset
Dim Connection
Dim aspDBcount
Dim ShowRowCount
ShowRowCount = 3 ' Fixed size
Set Connection = Server.CreateObject("ADODB.Connection")
Set Recordset = Server.CreateObject("ADODB.Recordset")
ConnString = "DRIVER={MySQL ODBC 5.3 Unicode Driver}; SERVER=server_address; UID=a_username;PASSWORD=a_password; OPTION=3; Port=a_port"
Connection.Open ConnString
SQL = "SELECT COUNT(*) AS MyRowCounts FROM `a_database`.`a_table`;"
Set Recordset = Connection.Execute(SQL)
aspDBcount = (Recordset("MyRowCounts") * 1)
Recordset.Close
MyTotalPages = (aspDBcount * 1) / (ShowRowCount * 1))
Response.Write aspDBcount & "HTML_NEW_LINE" & ShowRowCount & "HTML_NEW_LINE" & MyTotalPages
Output is 10, 3, 0
Should be 10, 3, 3.33333... (with current data available in database)

Use:
aspDBcount = cInt(Recordset("MyRowCounts")) * 1
In MySQL, SELECT COUNT() returns a BIGINT integer type and needs converting before you can manipulate it and use it properly in VBScript.
CInt can only convert numbers between -32,767 and 32,767
If your SELECT COUNT() exceeds this range you'll need to use CLng instead, which has a range of -2,147,483,648 to 2,147,483,647
You can also use CDbl, which is a bit of a weird one. It can convert HUGE numbers and doesn't seem to have an overflow. It will just eventually return an Invalid number error if you try to pass a ridiculously large integer.

Related

Date from SQL recordset missing milliseconds; auto-formatted to US locale

I am using the following code to retrieve a date from a SQL database.
set db = Server.CreateObject("ADODB.Connection")
db.Open dbConnection
Set c1 = Server.CreateObject("ADODB.Command")
Set c1.ActiveConnection = db
c1.CommandType = adCmdText
c1.CommandText = "SELECT [Date] FROM SomeTable WHERE ID=?"
c1.Parameters.Append c1.CreateParameter("#ID", adVarWChar, adParamInput, 255, CStr(ID))
set rs = Server.CreateObject("ADODB.Recordset")
rs.Open c1, , 1, 3
When printing rs("Date"), the date is printed as 12/1/2017 2:15:07PM.
Running the above query in the database returns this date 2017-12-01 14:15:06.675.
My overall goal is to not receive a date, that is rounded up to the next full second. I would rather receive a date where the milliseconds are stripped off and not than rounded up. In this case: 12/1/2017 2:15:06PM.
It would also be fine, to receive the date the same way the query returns the date: 2017-12-01 14:15:06.675
At this point I am not sure what causes this auto-formatting of the date.
Thank you very much for your help :-)
You can use DateDiff but the smallest unit it can return is seconds. No problem to get milliseconds from seconds though:
milliSecs = DateDiff("s", cdate("1970-01-01"), rs("Date")) * 1000
you'd probably be better off converting the column to a string and formatting the [date] column directly in sql:
c1.CommandText = "SELECT CONVERT( VARCHAR(24), [Date], 121) FROM SomeTable WHERE ID=?"
for more date formats, check out https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql

Checking content of textbox vb.net

I am using a text box for input to my SQL query. Based on the input I create a certain query and display the data in a gridview.
However I wish to make an adjustment for my users.
They often make an input like PL26... However this is not a valid name in the database to search for. Therefore I want to CHECK their input, and alter it accordingly, so they don't have to think about it.
I happen to know that when they type PL26 the correct input would be PL000026 ... The entity to search for is always "PL" + 6 characters/numbers... so if they wrote PL155, the number/string I pass to the sql query should become PL + 000 + 155 = PL000155.
I hope someone can help me how to accomplish this. That is if it is possible?
My idea/Pseudo code would be something like
If tbInput.txt's FIRST 2 CHARS are PL, then check total length of string
if StringLength < 8 characters, then
if length = 2 then ADD 4 0' after PL...
if length = 3 then add 3 0's after PL...
if length = 3 then add 3 0's after PL..
etc
....
...
Here we go:
Private Sub Button21_Click(sender As System.Object, e As System.EventArgs) Handles Button21.Click
Debug.Print(formatCode("PL1"))
Debug.Print(formatCode("PL"))
Debug.Print(formatCode("PL01"))
Debug.Print(formatCode("PL155"))
End Sub
Private Function formatCode(userInput As String) As String
Dim returnVal As String
If userInput.Length < 8 Then
returnVal = String.Concat(userInput.Substring(0, 2), userInput.Substring(2, userInput.Length - 2).PadLeft(6, "0"))
Else
returnVal = userInput
End If
Return returnVal
End Function
You may need to add some validation ensuring it starts with PL etc.
The following will work as long as there are no other non-numeric characters in between the PL and the numbers. You can always add it in your validation.
Dim newInput As String
If (input.StartsWith("PL")) Then
input = input.Remove(0, 2)
End If
' If this fails then it means the input was not valid
Dim numberPart = Convert.ToInt32(input)
newInput = "PL" + numberPart.ToString("D6")
Exctract a number by removing prefix "PL"
Parse to Integer
Use Custom Numeric Format Strings(zero placeholder) for adding zeros and prefix
Const PREFIX As String = "PL"
Dim exctractedNumber As Int32
If Int32.TryParse(tbInput.txt.Replace(PREFIX, String.Empty), exctractedNumber) = False Then
'Error nahdling
Exit Sub
End If
Dim finalFormat As String = String.Format("'{0}'000000", PREFIX)
Dim finalValue As String = exctractedNumber.ToString(finalFormat)
I would make use of the handy PadLeft method:
Dim input As String = "PL26"
Dim number As String = input.Substring(2, input.Length - 2)
If number.Length <> 6 Then
number = number.PadLeft(6, "0"C)
End If
MSDN String.PadLeft

Further problems with counting occurrences of strings in an Array

I am copying a question and answer from elsewhere as it partly goes into what I need but not completely.
In ASP classic, is there a way to count the number of times a string appears in an array of strings and output them based on string and occurrence count?
For example if I have an array which contains the following :
hello
happy
hello
hello
testing
hello
test
happy
The output would be:
hello 4
happy 2
test 1
testing 1
The answer that was given was this:
I'm assuming the language is VBScript (since that's what most people use with classic ASP).
You can use a Dictionary object to keep track of the individual counts:
Function CountValues(pArray)
Dim i, item
Dim dictCounts
Set dictCounts = Server.CreateObject("Scripting.Dictionary")
For i = LBound(pArray) To UBound(pArray)
item = pArray(i)
If Not dictCounts.Exists(item) Then
dictCounts.Add item, 0
End If
dictCounts.Item(item) = dictCounts.Item(item) + 1
Next
Set CountValues = dictCounts
End Function
This is great but I can't work out how to grab the top 2 most used words, display them and be able to put them in their own variable for use elsewhere.
Can anyone help with this?
You can loop through the dictionary object using this method. Inside that loop keep track of the top two keys and their counts in either a new array or two new variables.
You can't sort a Dictionary object in VBScript, so you have to use something else.
My advice is using a disconnected Recordset object to hold the items and their occurrences. Such object natively support sorting and it's pretty easy to use. To achieve this have such function instead:
Function CountValues_Recordset(pArray)
Dim i, item
Dim oRS
Const adVarChar = 200
Const adInteger = 3
Set oRS = CreateObject("ADODB.Recordset")
oRS.Fields.Append "Item", adVarChar, 255
oRS.Fields.Append "Occurrences", adInteger, 255
oRS.Open
For i = LBound(pArray) To UBound(pArray)
item = pArray(i)
oRS.Filter = "Item='" & Replace(item, "'", "''") & "'"
If (oRS.EOF) Then
oRS.AddNew
oRS.Fields("Item").Value = item
oRS.Fields("Occurrences").Value = 1
Else
oRS.Fields("Occurrences").Value = oRS.Fields("Occurrences").Value + 1
End If
oRS.Update
oRS.Filter = ""
Next
oRS.Sort = "Occurrences DESC"
oRS.MoveFirst
Set CountValues_Recordset = oRS
End Function
And using it to achieve the output you want:
Dim myArray, oRS
myArray = Array("happy", "hello", "hello", "testing", "hello", "test", "hello", "happy")
Set oRS = CountValues_Recordset(myArray)
Do Until oRS.EOF
Response.Write(oRS("item") & " " & oRS("Occurrences") & "<br />")
oRS.MoveNext
Loop
oRS.Close
Set oRS = Nothing
Don't forget to close and dispose the recordset after using it.

ADODB.Recordset AbsolutePage not working with Oracle Database (ASP.net)

I have the following code:
Dim PageNum AS Integer = 1
Dim ThePageSize As Integer = 30
Dim RowCT As Integer = 0
Dim SqlStr As String = "SELECT * FROM TheTable"
Dim TCConStr As String = ConfigurationManager.ConnectionStrings("TCConStr").ConnectionString
Dim Objrs As New ADODB.Recordset
Objrs.Open(SqlStr, TCConStr, 3, 3)
If Not Objrs.EOF Then
Objrs.MoveFirst()
Objrs.PageSize = ThePageSize
Dim TotalPages As Integer = Objrs.PageCount
Objrs.AbsolutePage = PageNum
End If
While Not Objrs.EOF And RowCT < Objrs.PageSize
RowCT = RowCT + 1
'Do Stuff
Objrs.MoveNext()
End While
Objrs.Close()
Objrs = Nothing
When I try to run it I get:
"System.Runtime.InteropServices.COMException: Current Recordset does not support bookmarks. This may be a limitation of the provider or of the selected cursortype."
The error page points to "Objrs.AbsolutePage = PageNum"
Any ideas of if I have done anything wrong here, or what I can do to get around it? It would kind of really stink to show 500 records on one page.
My somewhat naïve guess, given that I know very little about ADODB, is that the Oracle provider for ADODB doesn't support paging. The documentation for the AbsolutePage property does indeed suggest this:
The provider must support the appropriate functionality for this property to be available.
So, instead of doing the paging in your ADO and VB.NET, you could do the paging in your Oracle query.
The typical way of doing paging with Oracle is to use a query like the following. This returns the 31st to the 40th rows of the table some_table, which would be for the 4th page of 10-row pages:
SELECT a, b, c
FROM (SELECT a, b, c, ROWNUM as num
FROM some_table
WHERE ROWNUM <= 40)
WHERE num > 30
The two numbers in this query should be PageNum * ThePageSize and (PageNum - 1) * ThePageSize in that order.
Note that if the query you're attempting to page has an ORDER BY clause or a GROUP BY clause, you'll need to move that into another subquery. For example, if we needed to sort by column b and then page the results, we'd use something like:
SELECT a, b, c
FROM (SELECT a, b, c, ROWNUM as num
FROM (SELECT a, b, c
FROM some_table
ORDER BY b)
WHERE ROWNUM <= 40)
WHERE num > 30

Complex Linq Query--Trying to add a .Where() or .Any() predicate to reduce query complexity (in VB)

I'm having issues with a rather complex Linq query and I need some advice. This involves VB syntax so I need specific answers for that platform, as I have a lot of trouble translating the C# syntax to VB at times.
I have to join two main tables, and I need to filter the results by elements in an ASP.NET web form. These filters are created on the fly so I have to use a lot of where extensions to filter the query. I want to execute the query with as optimized SQL as possible.
I am first doing a simple join between TW_Sites and TW_Investigators. Then there are two sub-tables that are involved. TW_InvestigatorToArea and TW_InvestigatorToDisease. While most of the where clauses are working fine, I have found a performance issue that won't be an issue right now, but will be an issue as the table gets bigger.
The arrays DiseaseCategories and DiseaseAreas would be the results of a CheckBoxList result.
Protected Sub LoadResults()
' Get Dictionary of Filters
Dim FilterDictionary As OrderedDictionary = Session.Item("InvestigatorFilterDictionary")
' Initialize LinqToSql
Dim LinqDbHandler As TrialWatchDC = New TrialWatchDC(WebConfigurationManager.ConnectionStrings("DataSourceName").ConnectionString)
' Create List of Categories to Filter By
Dim DiseaseCategories() As Integer = {1, 2, 3, 4, 5, 6, 11, 22, 361, 77, 82, 99, 400}
Dim CategorySubQuery = From ic In LinqDbHandler.TW_InvestigatorsToDiseases Where DiseaseCategories.Contains(ic.DiseaseCategoryID) Select ic.InvestigatorID Distinct
' Dim CategorySubArray = CategorySubQuery.ToArray()
' Create List of Areas to Filter By
Dim AreaCategories() As Integer = {17, 1, 3, 5}
Dim AreaSubQuery = From ic In LinqDbHandler.TW_InvestigatorsToAreas Where AreaCategories.Contains(ic.AreaID) Select ic.InvestigatorID Distinct
Dim AreaSubArray = AreaSubQuery.ToArray()
Dim dc As DbCommand
Dim ThisQuery = From Site In LinqDbHandler.TW_Sites _
Join Investigator In LinqDbHandler.TW_Investigators On Site.TrialSiteID Equals Investigator.TrialSiteID _
Join SiteType In LinqDbHandler.TW_SiteTypes On Site.SiteTypeID Equals SiteType.SiteTypeID _
Order By Site.ResearchCenterName, Investigator.InvestigatorName
Select New With {.TrialSiteID = Site.TrialSiteID, _
.InvestigatorID = Investigator.InvestigatorID, _
.ResearchCenterName = Site.ResearchCenterName, _
.SiteTypeID = SiteType.SiteTypeID, _
.TypeLabel = SiteType.TypeLabel, _
.CenterState = Site.CenterState, _
.CenterCountry = Site.CenterCountry, _
.ContactName = Site.ContactName, _
.ContactEMail = Site.ContactEMail, _
.ContactPhone = Site.ContactPhone, _
.IsRcppSubscriber = Site.IsRcppSubscriber, _
.InvestigatorName = Investigator.InvestigatorName, _
.IsPublicationSubscriber = Investigator.IsPublicationSubscriber, _
.HasPhase01 = Investigator.HasPhase01, _
.HasPhase02 = Investigator.HasPhase02, _
.HasPhase03 = Investigator.HasPhase03, _
.HasPhase04 = Investigator.HasPhase04, _
.AreaList = String.Join(",", (From ia In LinqDbHandler.TW_InvestigatorsToAreas Join a In LinqDbHandler.Disease_Areas On ia.AreaID Equals a.Area_Number Where ia.InvestigatorID = Investigator.InvestigatorID Order By a.Area_Name Select a.Area_Name Distinct).ToArray()), _
.CategoryList = String.Join(",", (From id In LinqDbHandler.TW_InvestigatorsToDiseases Join d In LinqDbHandler.Disease_Categories On id.DiseaseCategoryID Equals d.Category_Number Where id.InvestigatorID = Investigator.InvestigatorID Order By d.Category_Name Select d.Category_Name Distinct).ToArray())}
If Not String.IsNullOrEmpty(FilterDictionary.Item("CountryFilter")) Then
ThisQuery = ThisQuery.Where(Function(s) s.CenterCountry = FilterDictionary.Item("CountryFilter").ToString())
End If
If Not String.IsNullOrEmpty(FilterDictionary.Item("SiteType")) Then
ThisQuery = ThisQuery.Where(Function(s) s.SiteTypeID = Convert.ToInt32(FilterDictionary.Item("SiteType")))
End If
dc = LinqDbHandler.GetCommand(ThisQuery)
If Not String.IsNullOrEmpty(FilterDictionary.Item("StateFilter")) Then
ThisQuery = ThisQuery.Where(Function(s) s.CenterState = FilterDictionary.Item("StateFilter").ToString())
End If
dc = LinqDbHandler.GetCommand(ThisQuery)
ThisQuery = ThisQuery.Where(Function(i) CategorySubArray.Contains(i.InvestigatorID))
ThisQuery = ThisQuery.Where(Function(i) AreaSubArray.Contains(i.InvestigatorID))
dc = LinqDbHandler.GetCommand(ThisQuery)
Trace.Warn("Command", dc.CommandText)
For Each dcp As SqlParameter In dc.Parameters
Trace.Warn(dcp.ParameterName.ToString(), dcp.Value.ToString())
Next
Dim ThisLinqResult = ThisQuery
InvestigatorResultGrid.DataSource = ThisLinqResult
InvestigatorResultGrid.DataBind()
End Sub
The big problem is, when you look at the code, basically I am first converting the filtered subqueries into an array and then passing it into the SQL code. The result ends up making an SQL Query with a lot of parameters, as seen below.
SELECT [t0].[TrialSiteID], [t1].[InvestigatorID], [t0].[ResearchCenterName], [t2].[SiteTypeID], [t2].[TypeLabel], [t0].[CenterState], [t0].[CenterCountry], [t0].[ContactName],
[t0].[ContactEMail], [t0].[ContactPhone], [t0].[IsRcppSubscriber], [t1].[InvestigatorName], [t1].[IsPublicationSubscriber], [t1].[HasPhase01], [t1].[HasPhase02], [t1].[HasPhase03],
[t1].[HasPhase04]
FROM [dbo].[TW_Sites] AS [t0]
INNER JOIN [dbo].[TW_Investigators] AS [t1] ON [t0].[TrialSiteID] = [t1].[TrialSiteID]
INNER JOIN [dbo].[TW_SiteTypes] AS [t2] ON [t0].[SiteTypeID] = ([t2].[SiteTypeID])
WHERE ([t1].[InvestigatorID] IN (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8, #p9, #p10, #p11, #p12, #p13, #p14, #p15, #p16, #p17, #p18, #p19, #p20, #p21, #p22, #p23, #p24, #p25, #p26, #p27,
#p28, #p29, #p30, #p31, #p32, #p33, #p34, #p35, #p36, #p37, #p38, #p39, #p40, #p41, #p42, #p43, #p44, #p45, #p46, #p47, #p48, #p49, #p50, #p51, #p52, #p53, #p54, #p55, #p56, #p57, #p58,
#p59, #p60, #p61, #p62, #p63, #p64, #p65, #p66, #p67, #p68, #p69, #p70, #p71, #p72, #p73, #p74, #p75, #p76, #p77, #p78, #p79, #p80, #p81, #p82, #p83, #p84, #p85, #p86, #p87, #p88, #p89,
#p90, #p91, #p92, #p93, #p94, #p95, #p96, #p97, #p98, #p99, #p100, #p101, #p102, #p103, #p104, #p105, #p106, #p107, #p108, #p109, #p110, #p111, #p112, #p113, #p114, #p115)) AND
([t1].[InvestigatorID] IN (#p116, #p117, #p118, #p119, #p120, #p121, #p122, #p123, #p124, #p125, #p126, #p127, #p128, #p129, #p130, #p131, #p132, #p133, #p134, #p135, #p136, #p137, #p138,
#p139, #p140, #p141, #p142, #p143, #p144, #p145, #p146, #p147, #p148, #p149, #p150, #p151, #p152, #p153, #p154, #p155, #p156, #p157, #p158, #p159, #p160, #p161, #p162, #p163, #p164, #p165,
#p166, #p167, #p168, #p169, #p170, #p171, #p172, #p173, #p174, #p175, #p176, #p177, #p178, #p179, #p180, #p181, #p182, #p183, #p184, #p185, #p186, #p187, #p188, #p189, #p190, #p191, #p192,
#p193, #p194, #p195, #p196, #p197, #p198, #p199, #p200, #p201, #p202, #p203, #p204, #p205))
ORDER BY [t0].[ResearchCenterName], [t1].[InvestigatorName]
This is a lot of parameters and will just get worse. Basically, instead of having a small IN clause with the conditions, I have a much larger IN clause with the investigator ids.
So, what I am trying to do is figure out how to, instead of converting the Area and Category queries into an array and then appending them to the third query, to get the queries to include the sub-tables and directly search for the matching ids of the areas and categories. I need to be able to use the predicate syntax since areas and categories are two sub-tables, and sometimes both or neither will be included. I know it has to do with either the .Any(), .Join(), or .Where() predicates, I just don't know how to get it to work.
Basically, I'm trying to change the SQL to make it look more like this.
WHERE ([t1].[InvestigatorID] IN (SELECT InvestigatorID FROM TW_InvestigatorsToAreas
WHERE DiseaseCategoryID IN (#p101, #p102, #p103)))
Any help or guidance would be appreciated.
Is this LINQ to SQL or EF?
Most ORMs will generate dynamic SQL with each ID for the IN statement as a parameter. Some smarter ones will create a temp table and join against that instead or use a nested subquery (or if you're really creative you might extend an ORM to do this).
I know DataObjects .NET does the temp table thing and LLBLGen can use nested subqueries for joins (aka prefetch pathes) and I'm sure there are at least a couple of others that do too.
One thing to note: Your mileage may vary. One big plus with a temp table is that you get around the 2400 parameter limit in SQL Server (though I'm not sure if that's an issue for you...). However, certain, maybe 1 in 20 queries will actually perform much much slower joining against a temp table (even an indexed one) vs. just passing in each ID as a parameter. Still, in general though, you'll have much better performance because the execution plan doesn't need to get re-compiled for each query.
It looks like it just came down to a syntax statement. I guess you just have to invoke the subquery from the LinqToSql object itself.
If DCHash.Count > 0 Then
ThisQuery = ThisQuery.Where(Function(i) (From ic In LinqDbHandler.TW_InvestigatorsToDiseases Where DiseaseCategories.Contains(ic.DiseaseCategoryID) Select ic.InvestigatorID).Contains(i.InvestigatorID))
End If
If AreaHash.Count > 0 Then
ThisQuery = ThisQuery.Where(Function(i) (From ia In LinqDbHandler.TW_InvestigatorsToAreas Where DiseaseAreas.Contains(ia.AreaID) Select ia.InvestigatorID).Contains(i.InvestigatorID))
End If

Resources