.Conversion error on unique identifier, shouldn't be referenced at all? - sql

I'm working on the shopping cart for a website, I have this function that retrieves a voucher from my database:
Public Shared Function CheckForVoucher(ByVal strVoucherName As String) As DataTable
Dim connect As New SqlConnection
Dim Data As New DataTable ''Connection works, finds number of Vouchers in DB that match either code or ID. ID to be used for randomly generated vouchers.
connect.ConnectionString = "SERVER = SERVER-SQL01; Trusted_Connection=yes; DATABASE=PCSQL"
connect.Open()
Dim query As String
Dim search As String
search = strVoucherName
If search.Length >= 25 Then
query = "SELECT * from PCSQL.dbo.X_WW_VOUCHER_DETAILS WHERE vID='" & search & "' "
Else
query = "SELECT * from PCSQL.dbo.X_WW_VOUCHER_DETAILS WHERE voucherName='" & search & "' "
End If
Dim command = New SqlDataAdapter(query, connect)
command.Fill(Data)
connect.Close()
strVoucherName = query
Return Data
End Function
This all works peachy-keen on the site I'm working on. At the end of a customers order it fires another function, the increase the totalUses of the voucher by one (my boss wants to make sure that people don't spam the codes and run him out of business).
Public Shared Function addUse(ByVal strVoucherName As String, intCurrentUses As Integer) As Boolean
Dim connect As New SqlConnection
Dim data As New DataTable
connect.ConnectionString = "SERVER = SERVER-SQL01; Trusted_Connection = yes; DATABASE=PCSQL"
connect.Open()
Dim query As String
Dim name As String = strVoucherName
Dim current As Integer = intCurrentUses
Dim newint As Integer = current + 1
query = "UPDATE dbo.X_WW_VOUCHER_DETAILS SET currentUses= #currentUses WHERE voucherName=#voucherName"
Dim command As New SqlCommand(query, connect)
command.Parameters.Add("#voucherName", SqlDbType.VarChar)
command.Parameters("#voucherName").Value = name
command.Parameters.Add("#currentUses", SqlDbType.Int)
command.Parameters("#currentUses").Value = newint
command.ExecuteNonQuery()
connect.Close()
Return True
End Function
This also works fine, and I can check the SQL table in SQL SERVER and see that the "currentUses" column has increased by one. Yay.
Problem
When I test the code by submitting again, it fails if the currentUses column is equal to the validUses column. I end up the error "Conversion failed when converting from a character string to uniqueidentifier" even though the Unique Identifier is not directly referenced at all.
I've tested on a voucher that is valid 5 times. Times 1 through 4, no errors but as soon as currentUses was also 5... no go.
Why would equal columns cause my function to crap itself?
SQL Table
-vID Uniqueidentifier
-voucherName Nchar(15)
-expiryDate Date
-validUses Int
-currentUses Int
-discountType Nchar(15)
-appliesTo Nchar(15)
-numberOf Nchar(20)
-Amount Int
-noOfItems Int
-Category Nchar(100)
-freebieID Nchar(15)
-discountAmount Int
-Description Nchar(255)
EDIT
I have narrowed the error down to this if statement.
If search.Length >= 25 Then
query = "SELECT * from PCSQL.dbo.X_WW_VOUCHER_DETAILS WHERE vID='" & search & "' "
Else
query = "SELECT * from PCSQL.dbo.X_WW_VOUCHER_DETAILS WHERE voucherName='" & search & "' "
End If
The Voucher itself is called from cart.aspx using
Protected Sub btnVoucherCheck_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnVoucherCheck.Click
Dim Data As DataTable = Voucher.CheckForVoucher(txtVoucher.text)
If Data.Rows.Count > 0 Then
Dim row As DataRow
row = Data.Rows(0)
Voucher.VoucherID = row.Item("vID").ToString().Trim()
Voucher.VoucherName = row.Item("voucherName").ToString().Trim()
Voucher.ExpiryDate = row.Item("ExpiryDate")
Voucher.ValidUses = row.Item("ValidUses")
Voucher.CurrentUses = row.Item("CurrentUses")
Voucher.DiscountType = row.Item("DiscountType").ToString().Trim()
Voucher.AppliesTo = row.Item("AppliesTo").ToString().Trim()
Voucher.NumberOf = row.Item("NumberOf").ToString().Trim()
Voucher.Amount = row.Item("Amount")
Voucher.noOfItems = row.Item("NoOfItems")
Voucher.Category = row.Item("Category").ToString().Trim()
Voucher.FreebieID = row.Item("FreebieID").ToString().Trim()
Voucher.DiscountAmount = row.Item("DiscountAmount")
Dim count As Int32
count = 0
Dim expiry As DateTime = Voucher.ExpiryDate
Dim today As DateTime = Date.Today()
count = ((expiry - today).Days)
If count <= -1 Then
txtVoucher.Text = "Voucher expired"
Else 'Further checks. One: Valid uses against current uses, checks if too many people have used the voucher.
If (Voucher.CurrentUses >= Voucher.ValidUses) Then
txtVoucher.Text = "Sorry, Voucher is no longer valid"
Else 'Redirects to one of three methods based on discount type.
c.VoucherName = Voucher.VoucherName
If c.discounted = True Then
For Each item As RepeaterItem In rptCart.Items
Dim quantity As TextBox = CType(item.FindControl("txtQuantity"), TextBox)
Dim ProductID As HyperLink = CType(item.FindControl("hlProductID"), HyperLink)
Dim lblPrice As Label = CType(item.FindControl("lblPrice"), Label)
lblPrice.Text = Product.GetProductPrice(ProductID.Text, quantity.Text, c)
Next
End If
Select Case Voucher.DiscountType
Case "Dollar"
txtVoucher.Text = "$ Not yet Supported"
Case "Percentage"
percentageDiscount()
Case "Freebie"
txtVoucher.Text = "Freebie Not Yet Supported"
Case Else
txtVoucher.Text = "Not working."
End Select
End If
End If
Else
End If
End Sub
The two relevant columns are compared in the middle of this function, but my code doesn't execute that far if they are equal to being with. I get the conversion error referencing the line in my CheckForVoucher function that I pasted above. It can't be my comparison that causes the error because the DataTable I use for that doesn't fully exist at the point the error occurs.

The problem you have is when the value of search is 25 characters or longer, you are passing it into the database to compare with the vID column. That column is a uniqueidentifier which means it's a GUID in C# terms. If the value you pass in cannot be converted directly to a GUID, then you will get a conversion error.

Related

Crystal Reports empty when printed during runtime(without viewer)

I'm developing a small POS system using VB.Net , MS Sql and Crystal Reports. I have no trouble viewing reports using Cry Rep Viewer. But when i try to print a bill during runtime the report becomes empty. Following is the sequence i'm executing within the procedure.
Generate bill no
Deduct qty from stocks
add the transaction from temp table to final sales table
print bill
delete temp table transactions
clear for next transaction
But my problem comes during the bill printing. Bill does not pickup the necessary records from the sales table. Following is my code for the end transaction. (I am using few of my own methods and functions which are from another class and im also using a fix bill no for testing)
I'm also attaching 2 bills. First 1 is the one viewed and exported from the Cry Report Viewer. The second one is the one with problem, and its empty even though the records exists in the table. Can some one kindly advice me on this matter?
Private Sub endCurrentTransaction()
Try
Dim sqlTempBill As String = "SELECT * FROM tb_transactions where cur_user='" & curUser & "'"
Dim sqlSales As String = "SELECT * FROM tb_sales where bill_no=''"
'Get Bill No
Dim newBillNo As String = generateBillNo()
'Deduct IT qty
Dim tempBill As DataTable
tempBill = myTbClass.myFunctionFetchTbData(sqlTempBill)
Dim i As Integer = 0
Dim curQty As Double = 0
Dim trQty As Double = 0
Dim updatedQty As Double = 0
For i = 0 To tempBill.Rows.Count - 1
curQty = 0
'Get the Current stock qty
Dim sqlgetCurQty As String = "SElECT cur_qty FROM tb_stock where it_batch_code='" & tempBill.Rows(i).Item("it_batch_code") & "'"
conn.Open()
Dim SqlCmdCurQty As New SqlCommand(sqlgetCurQty, conn)
Dim DataReadercurQty As SqlDataReader = SqlCmdCurQty.ExecuteReader
While DataReadercurQty.Read()
curQty = DataReadercurQty.Item(0)
End While
DataReadercurQty.Close()
conn.Close()
trQty = tempBill.Rows(i).Item("qty")
updatedQty = curQty - trQty
Dim sqlUpdateQtyString As String = "UPDATE tb_stock SET cur_qty=" & Math.Round((updatedQty), 3) & " Where it_batch_code='" & tempBill.Rows(i).Item("it_batch_code") & "'"
conn.Open()
Dim SqlCmdQty As New SqlCommand(sqlUpdateQtyString, conn)
SqlCmdQty.ExecuteNonQuery()
conn.Close()
'add to sales
Dim tempTbSales As DataTable
tempTbSales = myTbClass.myFunctionFetchTbData(sqlSales)
Dim dataRow As DataRow = tempTbSales.NewRow
dataRow("it_code") = Trim(tempBill.Rows(i).Item("it_code"))
dataRow("it_batch_code") = Trim(tempBill.Rows(i).Item("it_batch_code"))
dataRow("it_name") = Trim(tempBill.Rows(i).Item("it_name"))
dataRow("buy_price") = Math.Round(tempBill.Rows(i).Item("buy_price"), 3)
dataRow("sell_price") = Math.Round(tempBill.Rows(i).Item("sell_price"), 3)
dataRow("qty") = Math.Round(tempBill.Rows(i).Item("qty"), 3)
dataRow("gross_val") = Math.Round(tempBill.Rows(i).Item("gross_val"), 3)
dataRow("discount_val") = Math.Round(tempBill.Rows(i).Item("discount_val"), 3)
dataRow("net_val") = Math.Round(tempBill.Rows(i).Item("net_val"), 3)
dataRow("profit_profile") = Trim(tempBill.Rows(i).Item("profit_profile"))
dataRow("discount_profile") = Trim(tempBill.Rows(i).Item("discount_profile"))
dataRow("cus_name") = Trim(tempBill.Rows(i).Item("cus_name"))
dataRow("tr_type") = Trim(cmbTrans.Text)
dataRow("cr_card_type") = Trim(cmbCardType.Text)
dataRow("card_no") = Trim(txtCardNo.Text)
dataRow("bill_no") = newBillNo
dataRow("discount_profile") = Trim(tempBill.Rows(i).Item("cus_name"))
dataRow("cur_user") = curUser
dataRow("added_date") = curServerDateTime
tempTbSales.Rows.Add(dataRow)
Call myTbClass.MyMethodUpdateTable(sqlSales, tempTbSales)
Next
i = 0
'Print bill
Dim cash, balance As Double
Dim crepBill As New repBill
crepBill.SetDatabaseLogon("sa", dbPwd)
cash = Val(Me.txtCash.Text)
balance = Val(Me.txtBalance.Text)
crepBill.RecordSelectionFormula = "{TB_SALES.bill_no} ='" & "000015" & "'"
crepBill.DataDefinition.FormulaFields("txtCash").Text = Format(cash, "#0.00")
crepBill.DataDefinition.FormulaFields("txtBal").Text = Format(balance, "#0.00")
crepBill.PrintToPrinter(1, False, 0, 0)
crepBill.Dispose()
'delete temp bill table
For i = 0 To tempBill.Rows.Count - 1
tempBill.Rows(i).Delete()
Next
Call myTbClass.MyMethodUpdateTable(sqlTempBill, tempBill)
'reset front end
Call loadBill()
Call clearCurrentTransaction()
Call clearCurrentSubTotals()
Call clearCurCashBalance()
'Íncrease the bill no by 1
Call increaseBillNo()
txtItCode.Focus()
Catch ex As Exception
MsgBox("This error was generated at endCurrentTransaction()")
End Try
End Sub
I found out that report need to be refreshed before printing. Report will only take data if it is refreshed.
https://answers.sap.com/answers/13088178/view.html

Evaluate string on record table,

How to evaluate match on the record table with vb I have a code like this
Dim absenperintah As SqlCommand = New SqlCommand("Select * from mytable where kodetp ='109'", cekdata)
absenperintah.CommandType = CommandType.Text
cekdata.Open()
Dim valuex = "500"
Using cekbaca As SqlDataReader =
absenperintah.ExecuteReader(CommandBehavior.CloseConnection)
If cekbaca.Read = True Then
Dim nilxbaca = cekbaca("rumus_k") --> record in the table is 1906650*(3.7/100)
Dim nilmy = valuex + nilxbaca
Dim result = New DataTable().Compute(nilmy, Nothing)
MsgBox(result)
End If
cekbaca.Close()
End Using
cekdata.Close()
I get the result 185,070,546 it should be result =70,564.55
how to get result =70,564.55 from Dim nilHy = valuex + nilxbaca
Your problem is that you are declaring these numbers as strings and they are being calculated accordingly.
What you think you are doing:
500 + 1906650*(3.7/100) = 70,564.55
If you were processing these as numbers, it would perform math and your calculation would work.
However, you have declared these values as strings. Therefore the code is actually running like this:
"500" + "1906650*(3.7/100)" 'String concatenation. Not math.
5001906650*(3.7/100) = 185,070,546
Try this code instead:
Dim absenperintah As SqlCommand = New SqlCommand("Select * from mytable where kodetp ='109'", cekdata)
absenperintah.CommandType = CommandType.Text
cekdata.Open()
Dim valuex = "500"
Using cekbaca As SqlDataReader =
absenperintah.ExecuteReader (CommandBehavior.CloseConnection)
If cekbaca.Read = True Then
Dim nilxbaca = cekbaca("rumus_k") 'record in the table is "1906650*(3.7/100)"
Dim nilmy = valuex & " + " & nilxbaca 'makes "500 + 1906650*(3.7/100)"
'Note: your next line of code, DataTable.Compute() will evaluate a
' (string) formula over several rows.
Dim result = New DataTable().Compute(nilmy, Nothing)
'Based on this code here, you are only processing one row.
'Maybe .Compute() is totally unnecessary here.
'You would be better to say: result = 500 + nilxbaca
' or maybe declare valuex as integer, to help the compiler treat it like a number instead of a string.
' or maybe your original code did apply this formula over several rows.
' ... In that case, my example would fix your Compute() formula.
MsgBox(result)
End If
cekbaca.Close()
End Using
cekdata.Close()

How do I assign a column variable to winform textbox

have the following query
<WebMethod(Description:="Retrieve members of a Client List"), SoapHeader("MessageSoapHeader", direction:=SoapHeaderDirection.In)> _
Public Function GetClientListMembers() As DataSet
Dim RS As SqlDataReader
RS = objApp.ConnectUser(MessageSoapHeader.UID, MessageSoapHeader.PWD, MessageSoapHeader.Campaign, MessageSoapHeader.Keyword, LocalCommon.apSOAPAdvanced)
If objApp.ClassErrorsCount > 0 Then
Dim NX As New Exception
LLIB.ThrowSOAPException(objApp.Errors(1).Number, NX, objApp.DB, objApp.Errors(1).ErrorType, objApp.Errors(1).Description)
GetClientListMembers = New DataSet
Exit Function
End If
Dim Client As New SqlCommand("optinPaging", objApp.DB)
Client.CommandType = CommandType.StoredProcedure
AddSQLCmdParm(Client, "#Shortcode", SqlDbType.Int, "", objApp.ShortCode, 0)
AddSQLCmdParm(Client, "#Keyword", SqlDbType.VarChar, "", objApp.Keyword, 0)
GetClientListMembers = LLIB.GetDataSet(Client)
LLIB.RecordRowTransfer(GetClientListMembers.Tables(0).Rows.Count, LLIB.RowTransferDirection.ToClient, objApp)
LLIB.FunctionCount(objApp, "GetClientListMembers") 'This must be placed after the close of RS
GetClientListMembers.Tables(0).TableName = "Cell Numbers"
LLIB.RecordRowTransfer(GetClientListMembers.Tables(0).Rows.Count, LLIB.RowTransferDirection.ToClient, objApp)
'Now get the email stuff
LLIB.AddDataTable(GetClientListMembers, "Email Addresses", "SELECT EmailAddress,Keyword, dbo.fn_ToUTC(ActualOptInDate) AS ActualOptInDate FROM EmailOptins WHERE ShortCode='" & objApp.ShortCode & "' AND Keyword='" & objApp.Keyword & "' AND OptInState=2 ORDER BY EmailAddress", objApp)
If GetClientListMembers.Tables.Count > 1 Then LLIB.RecordRowTransfer(GetClientListMembers.Tables(1).Rows.Count, LLIB.RowTransferDirection.ToClient, objApp)
objApp.DB.Close()
End Function
One of the columns it returns is totalPages. This value is the the same for all rows
I need to display this in a textbox on the form. The name of the textbox is "pageCount"
I am not sure how to proceed.
In your client app you probably have something like this
ReturnedDS = AdvServer.GetClientListMembers()
Assuming that your database [stored procedure] call returns only one table
dim pgCount as integer = 0 'default value
' Check if your table actually has rows
If ReturnedDS.Tables(0).Rows.Count > 0 Then
' pick first row and specific column
pgCount = CInt(myDataset.Tables(0).Rows(0)("totalPages"))
End If
' set text box
pageCount.Text = pgCount.ToString()

Bus Driver Analysis Application: speeding up queries, for loops, and proper syntax

I'm working on a project, at work, called the "Bus Driver." The bus driver is a material handler that goes to 9 different assembly lines, on the production floor, and picks up finished goods (refurbished receivers) and drops them off at a converyer belt where they are then shrinked wrapped and sent to be palletized.
The application I'm working on tracks each time he makes one complete route and then stores his stats in an SQL DB.
The application that records his route stats works fine but I have another application called, "The Bus Driver Analyzer." This application gets all the Bus driver's data and produces 4 charts.
Chart 1: Route Efficiency (52 weeks are shown, in this chart, on the X-value)
Chart 2: On time delivery Rates (52 weeks are shown, in this chart, on the X-value)
Chart 3: Histogram Chart (there is a radio button for a YTD or Weekly option)
Chart 4: Stack Ranking chart (top 10)
The two charts below are the two charts i want to focus on for this question.
My problem with this application is that I have 52 labels, on the windows form, to hold his route efficiencies for each week (seen on your left.) They are called "LblWkEff1" and goes up to "LblWkEff52" and then I have another 52 labels, on the windows form to hold his On time delivery rates (Seen on your right.) They are called "lblDeliveryStat1" and go up to "lblDeliveryStat52."
The code I have to retrieve these results is horrendeous, from what i've been told, on this site, and I don't disagree. I'm still new to programming so what I have written is by no means clean and perfect.
here is my code:
Dim RESULT1 As Decimal 'declare this as global
Dim RESULT2 As Decimal 'declare this as global
Private Sub Week(ByVal week As Integer)
Dim queryString As String = "SELECT " & _
" (SELECT CAST(SUM(TARGET_SECONDS) AS DECIMAL)/ CAST(SUM(ROUTE_SECONDS) AS DECIMAL) FROM dbo.APE_BUSDRIVER_MAIN WITH(NOLOCK) WHERE WEEK_TIME = " & week & " AND APE_AREA_OBJID = " & lblAreaOBJID.Text & " AND EMPLOYEE_NAME = '" & cbEmployeeName.Text & "' AND YEAR_TIME = '" & cbYear.Text & "' AND ACTIVE = 1) AS RESULT1," & _
" (SELECT (SELECT CAST(COUNT(APE_BUSDRIVER_STATUS_OBJID) AS DECIMAL) FROM dbo.APE_BUSDRIVER_MAIN AS RESULT2 WHERE WEEK_TIME = " & week & " AND APE_AREA_OBJID = " & lblAreaOBJID.Text & " AND EMPLOYEE_NAME = '" & cbEmployeeName.Text & "' AND YEAR_TIME = '" & cbYear.Text & "' AND ACTIVE = 1 AND APE_BUSDRIVER_STATUS_OBJID = 1)/(SELECT CAST(COUNT(APE_BUSDRIVER_STATUS_OBJID) AS DECIMAL) FROM dbo.APE_BUSDRIVER_MAIN AS RESULT2 WHERE WEEK_TIME = " & week & " AND APE_AREA_OBJID = " & lblAreaOBJID.Text & " AND EMPLOYEE_NAME = '" & cbEmployeeName.Text & "' AND YEAR_TIME = '" & cbYear.Text & "' AND ACTIVE = 1)) AS RESULT2" & _
" FROM dbo.APE_BUSDRIVER_MAIN "
Using connection As New SqlConnection(SQLConnectionStr)
Dim command As New SqlCommand(queryString, connection)
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
' Call Read before accessing data.
If reader.HasRows Then
While reader.Read()
RESULT1 = reader("RESULT1")
RESULT2 = reader("RESULT2")
End While
Else
RESULT1 = 0
RESULT2 = 0
End If
' Call Close when done reading.
reader.Close()
End Using
End Sub Private Sub LoadWeeklyStats()
'LOOP AND QUERY
For i As Integer = 0 To 51
Week(i + 1)
Dim LabelWkEff As String = "LblWkEff" + (i + 1).ToString
Dim myArray1 As Array = Controls.Find(LabelWkEff, False)
Dim myControl1 As Label = myArray1(0)
myControl1.Text = RESULT1
'AND
Dim LabelDeliveryStat As String = "lblDeliveryStat" + (i + 1).ToString
Dim myArray2 As Array = Controls.Find(LabelDeliveryStat, False)
Dim myControl2 As Label = myArray2(0)
myControl2.Text = RESULT2
Next
End Sub
Private Sub LoadWeeklyStats() is what im using to hold the results and place them on the "LblWkEffXX" and "lblDeliveryStatXX" labels, on the windows form.
this process takes 5 seconds each time a new user is selected for reviewal and I know it has something to do with the SQL query and the for loop but I dont know how else to write the code to get the results I want more efficiently.
Any feedback on how to rewrite the code or what other option i can perform to achieve the same results in a much quicker time would be most appreciated.
please let me know if you need more information.
From a cursory look, I would suggest that there is nothing inherently wrong with what you are trying to do. I think the biggest problem is in the opening of 52 sql connections, which is a relatively expensive process.
Therefore I suggest that the simplest efficiency savings would be to either amend your query to get all the data back at once, or to simply pass the Connection instance into the Week() method.
Charting software, such as dundas and I'm sure even the built-in charting types, usually take in a multi-dimensional array of values: one value being the X axis value and one being the Y value axis. You should not need to set each label individually.
However, if you want to check where your efficiencies are lost in the current system, I'd comment out:
Dim myArray1 As Array = Controls.Find(LabelWkEff, False)
Dim myControl1 As Label = myArray1(0)
myControl1.Text = RESULT1
and
Dim myArray2 As Array = Controls.Find(LabelDeliveryStat, False)
Dim myControl2 As Label = myArray2(0)
myControl2.Text = RESULT2
This will tell you whether or not that 5 seconds is coming from the DB queries or if it's coming from the amount of Controls.Find calls you're making. You could just profile your code as well, but this is a pretty easy test. If it gets dramatically faster, then it's your Controls.Find and not your queries. If, however, it's still slow, then time to profile your query to see if a restructuring or an index is needed.
If it gets faster, your best bet is to create an array of controls on first load then use that array in subsequent fills. No need to find your controls each time -- they're not going to change!
Something like this workflow:
Create two new List(Of Label) member variables in your class -- one to store the LabelWkEff values and one to store the LabelDeliveryStat values.
On Form load, loop: For i As Integer = 0 To 51, doing the same code as before to find the controls.
Instead of setting their label values, add them to their new respective member variables
In the code you pasted, where before you were finding the control, use the i index to access the correct control from the new member variables, e.g. Dim myControl1 as Label = LabelWkEffs(i)
That should make things significantly faster, assuming your bottleneck is the Controls.Find.
Joseph, as many have mentioned, 52 round trips to database is not a good idea.
Here is what I tried to to:
Create a stored procedure that takes parameter and gets the 52 week statistics for a given driver at once.
Create procedure GetDriverStatsBetweenWeeks(
#area_objid int,
#emp_name varchar(255),
#year_time int,
#start_Week int = 1,
#end_Week int = 52
)
as
begin
declare #driver_stats table(weektime int, result1 decimal(38, 10), result2 decimal(38, 10))
declare #currentWeek int
set #currentWeek = #start_Week
while (#currentWeek <= #end_Week)
begin
insert into #driver_stats(weektime, result1, result2)
select
week_time
,(cast(sum(TARGET_SECONDS) AS DECIMAL)
/cast(sum(ROUTE_SECONDS) AS DECIMAL)) as Result1
,(cast(sum((case when APE_BUSDRIVER_STATUS_OBJID = 1 then 1 else 0 end)) as decimal)
/cast(sum((case when APE_BUSDRIVER_STATUS_OBJID <> 1 then 1 else 0 end)))) as Result2
FROM
dbo.APE_BUSDRIVER_MAIN a
WHERE
WEEK_TIME = #currentWeek AND APE_AREA_OBJID = #area_objid
AND EMPLOYEE_NAME = #emp_name and YEAR_TIME = #year_time AND ACTIVE = 1
group by week_time
set #currentWeek = #currentWeek + 1
end
select weektime, result1, result2 from #driver_stats
end
go
Create a data layer (dummy one) that connects to the sql server executes the above proc gets the results into a model
Public Class ClassDriverStatistics
Property Week As Integer = 0
Property Result1 As Decimal = 0.0 ' rename this property to something like RouteEffeciency
Property Result2 As Decimal = 0.0 ' rename this property to the appropriate name
Public Sub New()
End Sub
End Class
Public Class MyDataLayer
Public Shared Function GetWeeklyDriverStats(StartWeek Integer, _
EndWeek Integer, YearTime Integer, _
AreaObjId Integer, EmployeeName String) _
as List(Of ClassDriverStatistics)
Dim oDriverWeeklyStatsList As New List(Of ClassDriverStatistics)
Using connection As New SqlConnection(SQLConnectionStr)
Dim command As SqlCommand = New SqlCommand("GetDriverStatsBetweenWeeks", connection)
connection.CommandType = CommandType.StoredProcedure
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
Do While objReader.Read()
Dim rec As ClassDriverStatistics = New ClassDriverStatistics()
rec.Week = Convert.ToInt32(theObjReader("weektime"))
rec.Result1 = Convert.ToDecimal(theObjReader("result1"))
rec.Result2 = Convert.ToDecimal(theObjReader("result2"))
oDriverWeeklyStatsList.Add(rec)
Loop
objReader.Close()
End Using
Return oDriverWeeklyStatsList
End Function
End Class
Obviously, not much changes to the LoadWeeklyStats() except to replace the loop of queries with a loop through the list of data model objects
Private Sub LoadWeeklyStats()
Dim weeklyStats As List(Of ClassDriverStatistics) = _
MyDataLayer.GetWeeklyDriverStats(1, 52, cbYear.Text, _
lblAreaOBJID.Text, cbEmployeeName.Text)
For Each weekStat As String In weeklyStats
Dim LabelWkEff As String = "LblWkEff" + weekStat.Week.ToString
Dim myArray1 As Array = Controls.Find(LabelWkEff, False)
Dim myControl1 As Label = myArray1(0)
myControl1.Text = weekStat.Result1
Dim LabelDeliveryStat As String = "lblDeliveryStat" + weekStat.Week.ToString
Dim myArray2 As Array = Controls.Find(LabelDeliveryStat, False)
Dim myControl2 As Label = myArray2(0)
myControl2.Text = weekStat.Result2
Next
End Sub
Please bear in mind
This code is not tested because I couldn't
Some how, I couldn't get this code in stack overflow to be properly formatted
I'm good at C# but not at VB.NET, this is some thing I tried to provide an answer because this question is already posted earlier as performance-speeding-up-application
Please see if this improves any performance. Also, apply the other aspects that others here at SO gave above.

Best way to merge two Datatables

I need to marge two datatables with condition. I have a datatable where the data comes from a local XML Database and another datatable where the data comes from a remote SQL Server.
If any update made in the remote datatable I need to update/merge with the local datatable. Here is what I have so far:
Public Sub MargeTwoTable()
Dim SQL As String = ""
Dim RemoteTable As New DataTable
Dim LocalTable As DataTable
Dim dal As New DalComon
Dim yy As Integer = 0
Dim UpdateDate As String
Dim TableName As String = "V_Book_Price"
LocalTable = LoadDataTable(TableName, True)
UpdateDate = LocalTable.Compute("MAX(update_date)", Nothing)
SQL = "select * from V_Book_Price where Update_Date > '" & UpdateDate & "'"
RemoteTable = dal.GetDataSetBySQL(SQL).Tables(0)
If RemoteTable.Rows.Count > 0 Then
For i = 0 To RemoteTable.Rows.Count - 1
Dim st As DataRow
Dim mm() As DataRow = LocalTable.Select("ID = '" & RemoteTable.Rows(i).Item("ID") & "'")
If mm.Length = 0 Then
st = LocalTable.NewRow
For yy = 0 To RemoteTable.Columns.Count - 1
st(yy) = RemoteTable.Rows(i)(yy)
Next
LocalTable.Rows.Add(st)
Else
st = mm(0)
For yy = 0 To RemoteTable.Columns.Count - 1
If IsDate(RemoteTable.Rows(i)(yy)) Then
st(yy) = CDate(RemoteTable.Rows(i)(yy)).ToString("s")
Else
st(yy) = RemoteTable.Rows(i)(yy)
End If
Next
mm = Nothing
End If
Next
End If
End Sub
In this code data comes from the remote database which updates a date getter then the local database . Both tables have "ID" as the primary key. The code is working well, but the problem is that when more than 1000 records are updated this function takes too long using loops.
Not sure if can be applicable, but have you ever looked at the
DataTable.LoadDataRow() method?.
It seems a good candidate to substitute all of you code above.
Your code could be simplified to these lines
Dim row as DataRow
For Each row in RemoteTable.Rows
LocalTable.LoadDataRow(row.ItemArray, false)
Next
Another alternative could be the DataTable.Merge that could cut your code to a single line
LocalTable.Merge(RemoteTable, False)
However, the real effectiveness of these two methods depends on the schema compatibility and from the presence of AutoNumber (identity) columns.