Looping through SQLdatareader and comparing row values - sql

I have a function that calls a stored procedure. I need to compare the result to an input parameter. I keep getting a warning that the function does not return on all code paths, but I can't figure out where.
So, 2 questions:
1. Am I looping through the SqlDataReader correctly or should I fill a datatable with my reader results?
2. Where am I missing a return value?
Function code:
Function FZCheck(FZ As String) As Boolean
Dim constr As String = My.Settings.devTOD.ToString
Dim con As New SqlConnection(constr)
Dim cmd As New SqlCommand("spSelectFloodZones", con)
cmd.CommandType = CommandType.StoredProcedure
If con.State = ConnectionState.Closed Then
con.Open()
End If
Dim rdr As SqlDataReader
rdr = cmd.ExecuteReader
If rdr.HasRows Then
Do While rdr.Read
If String.Equals(rdr(0).ToString, FZ) = True Then
Return True
Else
Return False
End If
Loop
Else
Return False
End If
If con.State = ConnectionState.Open Then
con.Close()
End If
rdr.Close()
End Function
Stored proc code: (very simple)
ALTER PROCEDURE [dbo].[spSelectFloodZones]
AS
SET NOCOUNT ON
SET ROWCOUNT 0
-- ====================
-- Select flood zones
-- ====================
SELECT DISTINCT FloodZone
FROM TOD.dbo.FloodZones
Language is VB.NET, using SQL Server 2012.

Here you go with some minor refactoring.
Function FZCheck(FZ As String) As Boolean
Dim constr As String = My.Settings.devTOD.ToString
Dim con As New SqlConnection(constr)
Dim result As Boolean = False
Dim cmd As New SqlCommand("spSelectFloodZones", con)
cmd.CommandType = CommandType.StoredProcedure
If con.State = ConnectionState.Closed Then
con.Open()
End If
Dim rdr As SqlDataReader
rdr = cmd.ExecuteReader
If rdr.HasRows Then
Do While rdr.Read
If String.Equals(rdr(0).ToString, FZ) = True Then
result = True
End If
Loop
End If
If con.State = ConnectionState.Open Then
con.Close()
End If
rdr.Close()
Return result
End Function

Related

How to check if byte is null vb.net

I'm assigning background images to every button according to my SQL Server database. If a byte is null I get this error:
Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'.
I want to allow buttons with no background images, but the error is preventing me.
Here is what I attempted:
Dim strsql As String
Dim ImgSql() As Byte
Using con As New SqlConnection("constring")
con.Open()
strsql = "SELECT Imagen FROM Inventario WHERE ID=#ID"
Dim cmd As New SqlCommand(strsql, con)
ItemID = 1
cmd.Parameters.Add("#ID", SqlDbType.VarChar).Value = ItemID
Dim myreader As SqlDataReader
myreader = cmd.ExecuteReader
myreader.Read()
ImgSql = myreader("Imagen")
If ImgSql IsNot Nothing AndAlso ImgSql.Length > 0 Then
Dim ms As New MemoryStream(ImgSql)
btn1.BackgroundImage = Image.FromStream(ms)
con.Close()
Else
'do nothing
End If
End Using
Dim ItemID As Integer = 1
Dim sql As String = "SELECT Imagen FROM Inventario WHERE ID=#ID"
Using con As New SqlConnection("constring"), _
cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#ID", SqlDbType.Integer).Value = ItemID
con.Open()
Using myreader As SqlDataReader = cmd.ExecuteReader()
If myreader.Read() AndAlso Not DBNull.Value.Equals(myreader("Imagen")) Then
Dim ImgSql() As Byte = DirectCast(myreader("Imagen"), Byte())
Using ms As New MemoryStream(ImgSql)
btn1.BackgroundImage = Image.FromStream(ms)
End Using
End If
End Using
End Using
Based on this answer in C#, converted to vb.net and added NULL check
Using con As New SqlConnection("constring")
Using cmd = con.CreateCommand()
cmd.CommandText = "SELECT Imagen FROM Inventario WHERE ID=#ID"
Dim ItemID = 1
cmd.Parameters.AddWithValue("#ID", ItemID)
con.Open()
Dim res = cmd.ExecuteScalar()
If res IsNot Nothing Then
ImgSql = CType(res, Byte())
If ImgSql IsNot Nothing AndAlso ImgSql.Length > 0 Then
Dim ms As New MemoryStream(ImgSql)
btn1.BackgroundImage = Image.FromStream(ms)
End If
End If
End Using
End Using

vb.net problem with recursive function inside while cycle

I try to create XtraDiagram (with DataTable) but this topic is related on DataTable construction.
Exscuse me if i ask you this problem. This is recursion problem. My scope is populate DataTable with all member of hierarchical structure (like for example file system).
In the last while i try to cycle for all children finded. In this section, i call recursive function for continue the analisys. The routine start ok and analisys until the last box. But after come back without analyze the other children… The sqldatareader lost his function? Because?
Thanks very much anticipated.
Public Function CreateDiagram(connection As SqlConnection, IDdoc2 As Integer, IDdoc1 As Integer) As Integer
'creation XtraDiagram
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim strItemName As String = String.Empty
'creation item
dt.Rows.Add(IDdoc2, strItemName, IDdoc1, "")
'extract how many children there are
cmd.Connection = connection
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT IDdocumento_1 FROM tbRelazioniDocumenti WHERE
IDdocumento_2=" & IDdoc2
dr = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read()
'for every children
Return CreateDiagram(connection, dr.Item("IDdocumento_1"), IDdoc2)
End While
Else
Return 0
End If
cmd.Dispose()
dr.Close()
End Function
Public Function CreateDiagram2(connection As SqlConnection, IDdoc2 As Integer, IDdoc1 As Integer) As Integer
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim strItemName As String = String.Empty
Dim arr() As Integer
ReDim arr(0)
'tento di estrapolare i figli
cmd.Connection = connection
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT IDdocumento_1 FROM tbRelazioniDocumenti WHERE IDdocumento_2=" & IDdoc2
dr = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read()
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr)) = dr.Item("IDdocumento_1")
End While
Else
Return 0
End If
cmd.Dispose()
dr.Close()
Dim i As Integer
For i = 1 To UBound(arr)
Return CreateDiagram2(connection, arr(i), IDdoc2)
Next i
End Function
When you close the datareader it also closes the connection. This means that when you move back up the stack the connection is now closed.
Additionally, you've got return CreateDiagram in your while loop. This will cause the method to execute CreateDiagram once and then return to the previous level.
I would suggest either using a try ... finally block around the creation item and the last if statement with the dispose and close in the finally or using blocks so that the command and reader are automatically disposed.
Next, I'd be inclined to put the results from datareader into a temporary table, and then iterate through the results recusively so that you don't run into trouble with your connection being closed while it's still being used.
Finally, is there any reason why you're not using a DataAdapter, and DataAdapter.fill(DataTable)? Once it has filled you could then use DataTable1.Load(DataTable2.CreateDataReader, upsert) to add the new rows to the existing datatable. See the official microsoft documentation here https://learn.microsoft.com/en-us/dotnet/api/system.data.datatable.load?view=netframework-4.8#System_Data_DataTable_Load_System_Data_IDataReader_System_Data_LoadOption_
Try this, I know I've modified a lot.
Public Function CreateDiagram(connection As SqlConnection, IDdoc2 As Integer, IDdoc1 As Integer) As Integer
'creation XtraDiagram
Dim cmd As SqlCommand = New SqlCommand()
'Dim dr As SqlDataReader
Dim strItemName As String = String.Empty
' Dim dt As DataTable
'creation item
dt.Rows.Add(IDdoc2, strItemName, IDdoc1, "")
Dim tmpdt As DataTable = dt.Clone
Dim cmdstr As String = String.Format("SELECT IDdocumento_1, {2} as strItemName, {1} as IDdoc1, '' as columnName3 FROM tbRelazioniDocumenti WHERE IDdocumento_2={0}", {IDdoc2, IDdoc1, strItemName})
'extract how many children there are
cmd.Connection = connection
cmd.CommandType = CommandType.Text
'cmd.CommandText = "SELECT IDdocumento_1 FROM tbRelazioniDocumenti WHERE IDdocumento_2=" & IDdoc2
cmd.commandtext = cmdstr
Dim da As New SqlClient.SqlDataAdapter(cmd)
da.Fill(tmpdt)
cmd.Dispose()
dt.Load(tmpdt.CreateDataReader, LoadOption.Upsert)
' dr = cmd.ExecuteReader
'If dr.HasRows Then
If tmpdt.Rows.Count > 0 Then
For Each dr As DataRow In tmpdt.Rows
'for every children
CreateDiagram(connection, dr.Item("IDdocumento_1"), IDdoc2)
Next
End If
Return 0
'dr.Close()
End Function
Or this which is your original with minimal changes
Public Function CreateDiagram(connection As SqlConnection, IDdoc2 As Integer, IDdoc1 As Integer) As Integer
'creation XtraDiagram
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim l As New List(Of Integer)
Dim strItemName As String = String.Empty
Try
'creation item
dt.Rows.Add(IDdoc2, strItemName, IDdoc1, "")
'extract how many children there are
cmd.Connection = connection
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT IDdocumento_1 FROM tbRelazioniDocumenti WHERE
IDdocumento_2=" & IDdoc2
dr = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read()
l.Add(dr.Item("IDdocumento_1"))
End While
Else
Return 0
End If
Finally
cmd.Dispose()
dr.Close()
End Try
For Each value In l
'for every children
CreateDiagram(connection, value, IDdoc2)
Next
End Function

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

I can't return result from my SQL user function to my vb.net program

I'm pulling my hair out!!
I wrote a simple scalar function and now I'm tring to execute it from vb.net and get the result back but it always shows up as zero, even though when I call it in SSMS it returns the value of 1, which is what I expect.
The function looks like this:
Alter FUNCTION [dbo].[CheckParity]
(#test char(1) )
RETURNS int
AS
BEGIN
declare #result int
IF (SELECT SUM(REVENUEAMOUNT) FROM CommissionDetail WHERE RevenueType IN('P','S')) =
(SELECT SUM(SERVICEREVENUE + PRODUCTREVENUE) FROM SalesmanAttainment)
set #result = 1
else
set #result = 0
return #result
END
I grabbed the vb code from the web:
sql = "dbo.CheckSalesAttainmentParity"
Dim count As Integer
cnn = New OleDbConnection(conn.ConnectionString)
Try
cnn.Open()
cmd = New OleDbCommand(sql, cnn)
cmd.Parameters.Add("test", OleDbType.Integer)
cmd.Parameters("test").Direction = ParameterDirection.ReturnValue
cmd.ExecuteScalar()
count = cmd.Parameters("test").Value
cmd.Dispose()
cnn.Close()
sql = "dbo.CheckSalesAttainmentParity"
Dim count As Integer
cnn = New OleDbConnection(conn.ConnectionString)
Try
cnn.Open()
cmd = New OleDbCommand(sql, cnn)
cmd.Parameters.Add("test", OleDbType.Integer)
cmd.Parameters("test").Direction = ParameterDirection.ReturnValue
cmd.ExecuteScalar()
count = cmd.Parameters("test").Value
cmd.Dispose()
cnn.Close()
I'm totally stumped. I'd appreciate all ideas
Duh!
I left out this line of code:
cmd.CommandType = CommandType.StoredProcedure
You're using a SQL Server database so I'm not sure if there was a particular reason you used OleDbConnection instead of SqlConnection, but try this.
Dim Sql As String = "select Sample.dbo.CheckParity('a')"
Dim count As Integer
Dim cnn As SqlConnection
Dim cmd As SqlCommand
Try
cnn = New SqlConnection(conn.ConnectionString)
cnn.Open()
cmd = New SqlCommand(Sql, cnn)
count = CInt(cmd.ExecuteScalar())
Console.WriteLine(count)
Console.ReadKey()
Finally
cmd.Dispose()
cnn.Close()
End Try

Execute Reader return Nothing always when I pass GUID as paramter

Dim objconn As New System.Data.SqlClient.SqlConnection(sConnStr)
Dim objcmd As New System.Data.SqlClient.SqlCommand(sSpName, objconn)
Try
objcmd.CommandType = CommandType.StoredProcedure
objcmd.Parameters.Add(prmId)
objconn.Open()
Dim myReader As SqlDataReader
If objconn.State = ConnectionState.Open Then
myReader = objcmd.ExecuteReader()
'myReader = objcmd.ExecuteReader()
If myReader.HasRows Then
If myReader.Read() Then
myFile = New File(myReader)
End If
End If
End If
Can Any one suggest me. what would be wrong in the above code. ExecuteReader is throwing excepion. Invalid cast from string to GUID. But My Sqlparamter was already uniqueidentifier nothing cast. Any Idea?
CREATE PROCEDURE GetFileInfo
#Id uniqueidentifier
AS
BEGIN
SELECT Id, DI_ID, sFileName, ContentType FROM FilesUpload Where Id=#Id
The value in your variable prmId is not a GUID, or rather, needs to be specified as such.
Using conn As New SqlClient.SqlConnection("YourConnectionString")
Using cmd As SqlClient.SqlCommand = conn.CreateCommand()
cmd.CommandText = "GetFileInfo"
cmd.Parameters.Add("#Id", SqlDbType.UniqueIdentifier)
cmd.Parameters("#Id").Value = New Guid(prmId)
conn.Open()
Dim myReader As SqlDataReader = cmd.ExecuteReader()
If myReader.Read() Then
myFile = New File(myReader)
End If
End Using
End Using