Error BC30616: Variable 'DBConnect' hides a variable in an enclosing block - sql

I've adjusted some code which was written for me.. It sends out emails to my website members. I have added a part which selects items for sale on the site and puts them in the email (Featured items). However, I'm getting this error:
D:\domains\example.com\httpdocs\sendFeaturedEmail.aspx.vb(79): error
BC30616: Variable 'DBConnect' hides a variable in an enclosing block.
Can anyone please show me how the code should be changed to work? I'm a fairly new programmer.. I'm learning by changing code that was written for me. Many Thanks for any help at all.
Public Sub SelectEmailDetails()
Dim DBConnect As New DBConn
Dim conn As SqlConnection = DBConnect.Conn("DBConnectionString")
Dim cmd As SqlCommand = DBConnect.Command(conn, "SelectEmailDetails")
conn.Open()
Dim DR As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Dim counter As Integer = 0
While DR.Read
'While DR.Read And counter < 1
Dim txtSubject As TextBox = fmvEmail.FindControl("txtSubject")
Dim txtEmailReminderText As TextBox = fmvEmail.FindControl("txtEmailReminderText")
Dim mm As New MailMessage
mm.To.Add(New MailAddress(DR("emailAddress").ToString))
mm.From = New MailAddress("admin#example.com", "example.com")
mm.IsBodyHtml = True
mm.Subject = txtSubject.Text
Dim bodyText As New StringBuilder
bodyText.AppendLine("<html><head><style>body { font-family:tahoma; font-size:1.0em; }</style></head><body>")
bodyText.AppendLine("<p><a href='http://example.com'><img src='http://example.com/files/images/emailLogo.png' border='0' /></a></p>")
bodyText.AppendLine("<p>Hurry.. Find these and more bargains in our current sale before they're gone..</p>")
Dim DBConnect As New DBConn
Using db As DbConnection = DBConnect.Conn("DBConnectionString")
Dim cmd As SqlCommand = DBConnect.Command(db, "FeaturedEmail")
cmd.Parameters.Add(New SqlParameter("MyDate", SqlDbType.Date, ParameterDirection.Input)).Value = MySale.prevDOW(DayOfWeek.Sunday).ToString("d")
db.Open()
Dim DR As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
ltlItems.Text = ltlItems.Text & "<div style='width:90%; word-wrap: break-word; margin:0 auto;'>"
While DR.Read
Dim friendlyOrderID = DR("link")
Dim strText = "http://www.example.com/catalog/images/thumbnails/" & DR("strText")
bodyText.AppendLine("<a href='" & friendlyOrderID & "'><img src='" & strText & "' /></a>")
End While
cmd.Dispose()
cmd = Nothing
db.Dispose()
db.Close()
End Using
bodyText.AppendLine("</body></html>")
mm.Body = bodyText.ToString
Dim smtp As New SmtpClient
smtp.Send(mm)
counter = counter + 1
End While
cmd.Dispose()
cmd = Nothing
conn.Close()
conn = Nothing
End Sub

Related

Check if Row is already exist in table before inserting

Well its been a while since my last post about saving loops through checkboxlist.So I did manage to check the input before it saved into table, but somehow it couldnt save any data even if wasnt duplicate one.
Wanted to create a function to check if each checkboxlist is already present within the table but I cant manage it because it needs value from this script so I skip it.
Using conn2 As New SqlConnection()
conn2.ConnectionString = ConfigurationManager _
.ConnectionStrings("BackboneConnectionString").ConnectionString()
Using cmd As New SqlCommand
cmd.CommandText = "Insert into EL_MstFunctionalNilai values(#IDFunc, #nik, #IDFuncParent, #IDFuncChild, #IDFuncMtr, '', '', '0')"
cmd.Connection = conn2
conn2.Open()
For Each item As ListItem In CheckBoxList2.Items
If item.Selected Then
'cmd.Parameters.Clear()
Dim urutan As Int32 = GetNumberFunctional()
Dim str As String = item.Value.ToString
Dim strArr() As String = str.Split("_")
Dim IDFunctionalParent1 As String = strArr(0)
Dim IDFunctionalChild1 As String = strArr(1)
Dim IDFunctionalMtr1 As String = strArr(2)
cmd.CommandText = "select count(*)as numrows from el_mstFunctionalnilai where nik = #nik and idfuncmtr = #IDFuncMtr"
cmd.Parameters.AddWithValue("#nik", txtnik.Text)
cmd.Parameters.AddWithValue("#IDFuncMtr", IDFunctionalMtr1)
queryresult = cmd.ExecuteScalar()
If queryresult = 0 Then
cmd.Parameters.Clear()
cmd.Parameters.AddWithValue("#IDFunc", urutan)
cmd.Parameters.AddWithValue("#nik", txtnik.Text)
cmd.Parameters.AddWithValue("#IDFuncMtr", IDFunctionalMtr1) 'mtr
cmd.Parameters.AddWithValue("#IDFuncParent", IDFunctionalParent1) 'parent
cmd.Parameters.AddWithValue("#IDFuncChild", IDFunctionalChild1) 'child
cmd.ExecuteNonQuery()
'Label1.Text = queryresult --> already check if queryresult has value
End If
End If
Next
conn2.Close()
End Using
End Using
When its executed no error tho, so I cant figure it out what Im missing. Well how do I fix this up?
Thanks.
el_mstFunctionalnilai
EL_MstFunctionalNilai
Which is it? Be careful about capitalization.
I have guessed at all the SqlDbType Please check your database to get the actual types.
Code following your pattern with 2 hits to database.
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim queryResult As Integer
'Pass the connection string directly to the constructor of the connection
Using conn2 As New SqlConnection(ConfigurationManager.ConnectionStrings("BackboneConnectionString").ConnectionString())
'Pass the command text and the connection directly to the command constructor
'You do not need as alias for Count
Using cmd As New SqlCommand("select count(*) from EL_MstFunctionalNilai where nik = #nik and idfuncmtr = #IDFuncMtr", conn2)
conn2.Open()
'This value does not appear to change in the loop so I moved it outside the loop
Dim urutan As Int32 = GetNumberFunctional()
'Add the parameters outside of the loop and only change the value inside the loop
'The value of the text box can't change inside the loop so it can be assigned outside the loop
cmd.Parameters.Add("#nick", SqlDbType.Int).Value = CInt(txtnik.Text)
cmd.Parameters.Add("#IDFuncMtr", SqlDbType.VarChar)
Using cmd2 As New SqlCommand("Insert into EL_MstFunctionalNilai values(#IDFunc, #nik, #IDFuncParent, #IDFuncChild, #IDFuncMtr, '', '', '0')", conn2)
cmd2.Parameters.Add("#IDFunc", SqlDbType.Int).Value = urutan
cmd2.Parameters.Add("#nik", SqlDbType.Int).Value = CInt(txtnik.Text)
cmd2.Parameters.Add("#IDFuncMtr", SqlDbType.VarChar) 'mtr
cmd2.Parameters.Add("#IDFuncParent", SqlDbType.VarChar) 'parent
cmd2.Parameters.Add("#IDFuncChild", SqlDbType.VarChar) 'child
For Each item As ListItem In CheckBoxList2.Items
If item.Selected Then
Dim str As String = item.Value.ToString
Dim strArr() As String = str.Split("_"c)
Dim IDFunctionalParent1 As String = strArr(0)
Dim IDFunctionalChild1 As String = strArr(1)
Dim IDFunctionalMtr1 As String = strArr(2)
cmd.Parameters("#IDFuncMtr").Value = IDFunctionalMtr1
queryResult = CInt(cmd.ExecuteScalar())
If queryResult = 0 Then
cmd2.Parameters("#IDFuncMtr").Value = IDFunctionalMtr1 'mtr
cmd2.Parameters("#IDFuncParent").Value = IDFunctionalParent1 'parent
cmd2.Parameters("#IDFuncChild").Value = IDFunctionalChild1 'child
cmd.ExecuteNonQuery()
End If
End If
Next
End Using
End Using
End Using
End Sub
I think it would be easier using one query that both checks for the existence of the record and inserts it if it doesn't exist.
Protected Sub Method2()
Dim urutan As Int32 = GetNumberFunctional()
Using cn As New SqlConnection(ConfigurationManager.ConnectionStrings("BackboneConnectionString").ConnectionString())
Using cmd As New SqlCommand("If Exists (Select 1 From EL_MstFunctionalNilai where nik = #nik and idfuncmtr = #IDFuncMtr) Select 0 Else Select 1 Insert into EL_MstFunctionalNilai values(#IDFunc, #nik, #IDFuncParent, #IDFuncChild, #IDFuncMtr, '', '', '0');", cn)
cmd.Parameters.Add("#nik", SqlDbType.Int).Value = CInt(txtnik.Text)
cmd.Parameters.Add("#IDFuncMtr", SqlDbType.VarChar)
cmd.Parameters.Add("#IDFunc", SqlDbType.VarChar).Value = urutan
cmd.Parameters.Add("#IDFuncParent", SqlDbType.VarChar)
cmd.Parameters.Add("#IDFuncChild", SqlDbType.VarChar)
cn.Open()
For Each item As ListItem In CheckBoxList2.Items
If item.Selected Then
Dim strArr() As String = item.Value.ToString.Split("_"c)
cmd.Parameters("#IDFuncMtr").Value = strArr(2)
cmd.Parameters("#IDFuncParent").Value = strArr(0)
cmd.Parameters("#IDFuncChild").Value = strArr(1)
cmd.ExecuteScalar()
End If
Next
End Using
End Using
End Sub

i want to use transaction with my code in VB.NET

I am using SqlDataAdapter and SqlCommandBuilder to insert and update, and I want to use transaction to insert into two tables with this way but I have tried a lot and I didn't succeed
thanks
Dim sql = "select * from ReceiptOfItems where receiptCode=N'" & receiptCode.Text & "' "
Dim dta As New SqlClient.SqlDataAdapter(sql, con)
Dim ds As New DataSet
dta.Fill(ds)
Dim dt As DataTable
dt = ds.Tables(0)
If dt.Rows.Count > 0 Then
' MsgBox("اسم االتصنيفل او رقمه موجود مسبقا ", MsgBoxStyle.Exclamation, "رسالة تنبيه")
receiptCode.Text = Format(Val(GetLastRecord("ReceiptOfItems", "receiptcode")) + 1, "REC0000000")
End If
Dim dr = dt.NewRow
dr!receiptCode = receiptCode.Text
dr!receiptDate = Format(receiptDate.Value, "yyyy/MM/dd")
' dr!receiptDate = receiptDate.Text
dr!supplierCode = GetsupplierCode(supplierName.Text)
dr!SupplierInvoiceCode = SupplierInvoiceCode.Text
dr!supplierInvoiceDate = Format(supplierInvoiceDate.Value, "yyyy/MM/dd")
'dr!supplierInvoiceDate = supplierInvoiceDate.Text
dr!TotalDiscount = Val(TotalDiscount.Text)
dr!TotalReceipt = Val(TotalReceipt.Text)
dr!TotalArabic = TotalArabic.Text
dr!SupplierInvoiceType = SupplierInvoiceType.Text
dr!salesTax = Val(salesTax.Text)
dr!note = note.Text
dr!status = True
dt.Rows.Add(dr)
Dim cmd As New SqlCommandBuilder(dta)
This should work for you:
con.Open()
Dim trans As SqlTransaction = con.BeginTransaction()
Try
Dim insertStr As String = "insert into ReceiptOfItems (receiptCode, receiptDate, etc.) values(#receiptCode, #receiptDate, #etc)"
Dim insertCmd As New SqlCommand(insertStr, con, trans)
For Each dc As DataColumn In dt.Columns
Dim param As New SqlParameter()
param.ParameterName = dc.ColumnName
param.SourceColumn = dc.ColumnName
insertCmd.Parameters.Add(param)
Next
dta.InsertCommand = insertCmd
dta.Update(ds)
trans.Commit()
con.Close()
Catch ex As Exception
trans.Rollback()
End Try
The DataAdapter class has an UpdateCommand and a DeleteCommand property which must be built appropriately if you are doing something other than inserting new rows.

Sending updates from datagridview to existing row in database

I am retrieving records from a database with the following code.
Dim SearchID As Integer = teacherID
Dim NewStudentID As Integer = studentID
Dim DisplayTable As New DataTable()
Dim da As New OleDbDataAdapter()
Dim sqlquery As String = ("select * from tblAppointments WHERE TeacherID =" & teacherID & "")
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Try
da.SelectCommand = New OleDbCommand(sqlquery, conn)
da.Fill(Finalds, "Display")
DisplayTable = Finalds.Tables("Display")
DisplayTable.Columns.Remove("Instrument")
DisplayTable.Columns.Remove("Room")
DisplayTable.Columns.Remove("TeacherID")
Registersgridview.DataSource = DisplayTable
Registersgridview.Columns(0).Visible = False
conn.Close()
Catch ex As Exception
MsgBox("There are no appointments in the database for " + Tutorcombox.Text)
End Try
It also there then added to a datagridview and certain columns are removed and some are hidden aswell.
Because its essentially a register, when the use clicks on the datagridview field that is a boolean it changes from false to true. I have been trying to send this back to the database, but have had no luck. I have tried the following :
Dim dt As DataTable = New DataTable("SendTable")
Dim row As DataRow
dt.Columns.Add("appID", Type.GetType("System.Int32"))
dt.Columns.Add("Present", Type.GetType("System.Boolean"))
For i = 0 To Registersgridview.Rows.Count - 1
row = dt.Rows.Add
row.Item("appID") = Registersgridview.Rows(i).Cells(0)
row.Item("Present") = Registersgridview.Rows(i).Cells(5)
Next
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim sqlquery As String = "Update tblAppointments SET Present = #Present WHERE appID = #appID"
Dim sqlcommand As New OleDbCommand
For Each newrow As DataRow In dt.Rows
With sqlcommand
.CommandText = sqlquery
.Parameters.AddWithValue("#Present", newrow.Item(1))
.Parameters.AddWithValue("#appID", newrow.Item(0))
.ExecuteNonQuery()
End With
conn.Close()
Next
But have had no luck with doing so, as it crashes without an error.
Can anyone help?
I solved the problem myself, if any of you are having similar problems here is the solution
Dim dt As DataTable = New DataTable("SendTable")
Dim row As DataRow
dt.Columns.Add("appID", Type.GetType("System.Int32"))
dt.Columns.Add("Present", Type.GetType("System.Boolean"))
For i = 0 To Registersgridview.Rows.Count - 1
Dim appID As Integer = Registersgridview.Rows(i).Cells(0).Value
Dim present As Boolean = Registersgridview.Rows(i).Cells(4).Value
row = dt.Rows.Add
row.Item("appID") = appID
row.Item("Present") = present
Next
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim sqlquery As String = "UPDATE tblAppointments SET Present = #Present WHERE appID = #appID"
Dim sqlcommand As New OleDbCommand
For Each newrow As DataRow In dt.Rows
With sqlcommand
.CommandText = sqlquery
.Parameters.AddWithValue("#Present", newrow.Item(1))
.Parameters.AddWithValue("#appID", newrow.Item(0))
.Connection = conn
.ExecuteNonQuery()
End With
Next
conn.Close()
Registersgridview.DataSource = Nothing
dt.Clear()
try this:
Dim dt As DataTable = New DataTable("SendTable")
Dim row As DataRow
dt.Columns.Add("appID", Type.GetType("System.Int32"))
dt.Columns.Add("Present", Type.GetType("System.Boolean"))
For i = 0 To Registersgridview.Rows.Count - 1
row = dt.Rows.Add
row.Item("appID") = Registersgridview.Rows(i).Cells(0)
row.Item("Present") = Registersgridview.Rows(i).Cells(5)
Next
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim sqlquery As String = "Update tblAppointments SET Present = #Present WHERE appID = #appID"
Dim sqlcommand As New OleDbCommand
For Each newrow As DataRow In dt.Rows
With sqlcommand
.CommandText = sqlquery
.Parameters.AddWithValue("#Present", newrow.Item(5))
.Parameters.AddWithValue("#appID", newrow.Item(0))
.ExecuteNonQuery()
End With
conn.Close()
Next

TransactionScope committing on each loop

Please see the code below:
Private Sub TransactionExample3()
Dim objDR As SqlDataReader
Dim objCommand As SqlCommand, objCommand2 As SqlCommand
Dim objCon As SqlConnection
Dim objCon2 As SqlConnection
Dim id As Integer
Dim list As List(Of Integer) = New List(Of Integer)
Try
_ConString = "Data Source=databaseserver;Initial Catalog=Person;User ID=username;Password=password;MultipleActiveResultSets=True"
list.Add(1)
list.Add(2)
list.Add(3)
For Each i As Integer In list
Using trans = New TransactionScope()
objCon2 = New SqlConnection(_ConString)
objCon2.Open()
objCommand2 = New SqlCommand()
objCommand2.Connection = objCon2
Using objCon2
objCommand2.CommandText = "UPDATE Person SET forenames = #forenames WHERE " & _
" Reference = #Reference "
objCommand2.Parameters.AddWithValue("#forenames", i + 1)
objCommand2.Parameters.AddWithValue("#Reference", i)
objCommand2.ExecuteNonQuery()
objCommand2.Parameters.Clear()
End Using
trans.Complete()
End Using
Next
Catch ex As Exception
Throw
Finally
End Try
End Sub
This code works i.e. on each loop the changes are committed to the database.
Now please see the code below:
Private Sub TransactionExample3()
Dim objDR As SqlDataReader
Dim objCommand As SqlCommand, objCommand2 As SqlCommand
Dim objCon As SqlConnection
Dim objCon2 As SqlConnection
Dim id As Integer
Try
_ConString = "Data Source=server;Initial Catalog=Person;User ID=Username;Password=Password;MultipleActiveResultSets=True"
objCon = New SqlConnection(_ConString)
objCommand = New SqlCommand("SELECT top 10 * from Person")
objCommand.Connection = objCon
objCon.Open()
objDR = objCommand.ExecuteReader()
Do While objDR.Read
objCon2 = New SqlConnection(_ConString)
objCon2.Open()
Using trans = New TransactionScope()
objCommand2 = New SqlCommand()
objCommand2.Connection = objCon
Using objCon2
objCommand2.CommandText = "UPDATE Person SET forenames = #forenames WHERE " & _
" Reference = #Reference "
objCommand2.Parameters.AddWithValue("#forenames", objDR("Reference") + 10)
objCommand2.Parameters.AddWithValue("#Reference", objDR("Reference"))
objCommand2.ExecuteNonQuery()
objCommand2.Parameters.Clear()
End Using
End Using
Loop
objDR.Close() 'line 16
Catch ex As Exception
Throw
Finally
End Try
End Sub
In the second code exherpt, the scope is not complete (scope.complete), however the results are still committed to the database on each iteration of the while loop. Why is this?
In the first loop the opening of the TransactionScope is before the opening of the connection. In the second one is after. The connection is not enlisted in the Transaction and thus every command executes without being held by a transaction.
Try to switch these lines
Do While objDR.Read
Using trans = New TransactionScope()
objCon2 = New SqlConnection(_ConString)
objCon2.Open()
.....
Now you need the call to trans.Complete()
Private Sub TransactionExample3()
Dim objDR As SqlDataReader
Dim objCommand As SqlCommand, objCommand2 As SqlCommand
Dim objCon As SqlConnection
Dim objCon2 As SqlConnection
Dim id As Integer
_ConString = "Data Source=server;Initial Catalog=Person;User ID=Username;Password=Password;MultipleActiveResultSets=True"
Using objCon = New SqlConnection(_ConString)
objCommand = New SqlCommand("SELECT top 10 * from Person")
objCommand.Connection = objCon
objCon.Open()
objDR = objCommand.ExecuteReader()
Using trans = New TransactionScope()
Using objCon2 = New SqlConnection(_ConString)
objCon2.Open()
Do While objDR.Read
objCommand2 = New SqlCommand()
objCommand2.Connection = objCon
Using objCon2
objCommand2.CommandText = "UPDATE Person SET forenames = #forenames WHERE " & _
" Reference = #Reference "
objCommand2.Parameters.AddWithValue("#forenames", objDR("Reference") + 10)
objCommand2.Parameters.AddWithValue("#Reference", objDR("Reference"))
objCommand2.ExecuteNonQuery()
objCommand2.Parameters.Clear()
End Using
Loop
objDR.Close() 'line 16
End Using
trans.Complete()
End Using
End Using
End Sub
I suggest to move the Transaction and Connection opening outside the loop and call the Complete and destroy the connection after the foreach loop, if I understand your code correctly you update one record at each loop and so the Transaction makes sense only if you want to update all of your records or none. Another minor optimization could be to move the creation of the SqlCommand and the Parameters outside the loop. You update just the parameters value inside the loop without destroying and rebuilding the parameter collection at each loop

Using SQLDataReader instead of recordset

I am new to this and had this question. Can I use SQLDataReader instead of a Recordset. I want to achieve the following result in an SQLDataReader.
Dim dbConn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim sqlstr As String = "SELECT Name,Status FROM table1 WHERE id=" + item_id.Value.ToString
rs.Open(SQL, dbConn)
While Not rs.EOF
txtName.Text = rs.Fields.Item("Name").Value
ddlstatus.SelectedIndex = 1
rs.MoveNext()
End While
rs.Close()
rs = Nothing
dbConn.Close()
dbConn = Nothing
Can I replace recordset with SQLDataReader and if I can can you please show me the changes in code?
Its highly recommend that you use the using pattern:
Dim sConnection As String = "server=(local);uid=sa;pwd=PassWord;database=DatabaseName"
Using Con As New SqlConnection(sConnection)
Con.Open()
Using Com As New SqlCommand("Select * From tablename", Con)
Using RDR = Com.ExecuteReader()
If RDR.HasRows Then
Do While RDR.Read
txtName.Text = RDR.Item("Name").ToString()
Loop
End If
End Using
End Using
Con.Close()
End Using
You will have to swap out a few things, something similar to the following.
Here is an example, you will need to modify this to meet your goal, but this shows the difference.
I also recommend using a "Using" statement to manage the connection/reader. Also, a parameterized query.
Dim sConnection As String = "server=(local);uid=sa;pwd=PassWord;database=DatabaseName"
Dim objCommand As New SqlCommand
objCommand.CommandText = "Select * From tablename"
objCommand.Connection = New SqlConnection(sConnection)
objCommand.Connection.Open()
Dim objDataReader As SqlDataReader = objCommand.ExecuteReader()
If objDataReader.HasRows Then
Do While objDataReader.Read()
Console.WriteLine(" Your name is: " & Convert.ToString(objDataReader(0)))
Loop
Else
Console.WriteLine("No rows returned.")
End If
objDataReader.Close()
objCommand.Dispose()
Dim rdrDataReader As SqlClient.SqlDataReader
Dim cmdCommand As SqlClient.SqlCommand
Dim dtsData As New DataSet
Dim dtbTable As New DataTable
Dim i As Integer
Dim SQLStatement as String
msqlConnection.Open()
cmdCommand = New SqlClient.SqlCommand(SQLStatement, msqlConnection)
rdrDataReader = cmdCommand.ExecuteReader()
For i = 0 To (rdrDataReader.FieldCount - 1)
dtbTable.Columns.Add(rdrDataReader.GetName(i), rdrDataReader.GetFieldType(i))
Next
dtbTable.BeginLoadData()
Dim values(rdrDataReader.FieldCount - 1) As Object
While rdrDataReader.Read
rdrDataReader.GetValues(values)
dtbTable.LoadDataRow(values, True)
End While
dtbTable.EndLoadData()
dtsData.Tables.Add(dtbTable)
msqlConnection.Close()
Return dtsData