Data is Null when trying to run basic stored procedure - vb.net

I created this simple test for reading data from a stored procedure. I must be overlooking something obvious, because I can't figure out why I'm continuing to get no data.
myReader.HasRows is always true.
I noticed that it is returning the correct number of rows, but I am having trouble getting at any data that might be in the rows.
Stored Procedure
ALTER PROCEDURE [dbo].[testProc]
-- Add the parameters for the stored procedure here
#carID uniqueidentifier
AS
BEGIN
SELECT * FROM carTable WHERE carID=#carID
END
VB.Net
Dim cmd As New SqlClient.SqlCommand("testProc", _conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("carID", carID)
_conn.Open()
Dim myReader As SqlDataReader
myReader = cmd.ExecuteReader()
If myReader.HasRows = True Then
While (myReader.Read())
If Not IsDBNull(myReader.GetString(0)) Then
' do stuff here
End If
End While
End If

From MSDN about SqlDataReader.GetString Method method:
No conversions are performed; therefore, the data retrieved must
already be a string.
Call IsDBNull to check for null values before
calling this method.
My guess is IsDBNull.myReader.GetString(0) returns False because CarId is not a String column (it's uniqueidentifier).
Instead, to test is the value is null, try to use the SqlDataReader.IsDBNull Method, which apply to any datatype.
If Not myReader.IsDBNull(0) Then

First, try running the query in your management studio with the supplied car ID to see what results it is passing back. Secondly I would try to change the if statement as follows and see if you still have issues:
If Not myReader.IsDBNull(0) Then
Additionally, all subsequent fields that allow NULL values must be checked for IsDBNull before they are used. This may also cause some issues.

Related

DataReader running very slow

I'm currently working with a database of over 50 million records, where I read a file which a person wants to search the database for etc. I have noticed my data reader part is running particularly slow, where as the query seems almost instant (database is indexed). I was just wondering does anyone know as to why it seems to be running slow?
con.Open()
Using sw As New StreamWriter("G:\USER\SEARCH-RESULTS.txt")
Try
For Each word As String In result
Using com As New SqlCommand("select t.SmeNbr, t.FilPth, r.MaxDate, t.DteAdd, t.LnePos from (Select SmeNbr, MAX(FilDte) as MaxDate from Test_Table where SmeNbr = #word group by SmeNbr)r inner join Test_Table t on t.SmeNbr = r.SmeNbr and t.FilDte = R.MaxDate", con)
com.Parameters.AddWithValue("#word", word)
Using RDR = com.ExecuteReader
If RDR.HasRows Then
Do While RDR.Read
MyFilePath = RDR.Item("FilPth").ToString()
linePos = RDR.Item("LnePos").ToString()
Using sr As New StreamReader(MyFilePath)
sr.BaseStream.Seek(4096 * (linePos - 1), SeekOrigin.Begin)
FoundWords.Add(sr.ReadLine)
For Each item As String In FoundWords
sw.WriteLine(item)
Next
FoundWords.Clear()
End Using
Loop
Else
Continue For
End If
End Using
End Using
Next
Catch ex As Exception
MessageBox.Show("Couldn't process search")
Finally
con.Close()
End Try
End Using
MsgBox("Complete!")
So it works perfect, as in it gets the records and bits of info I want very quickly through the query and all and even the writing reults to a new file is near instant, I used breakpoints and like I said it seems to take ages between the "Using RDR = com.ExecuteReader" and "If RDR.HasRows Then"
Any help or ideas would be greatly appreciated.
com.Parameters.AddWithValue("#word", word)
AddWithValue infers the parameter data type from the provided .NET object value. Since .NET strings are Unicode, this code is will add an nvarchar(n) parameter with the length of the actual value. I see from your comments that the actual column data type is char(13) so it would be best to explicitly specify that as the parameter data type:
com.Parameters.Add("#word", SqlDbType.Char, 13).Value = word
The implications with AddWithValue are that indexes might not be used due to the mismatched data type and there may be many variations of the same query in the SQL Server procedure cache that differ only by length. For these reasons, I suggest one avoid AddWithValue.

Specified cast is not valid with datareader

Hi friends of stackoverflow,
I'm writing a question here because i'm having problems to detect why sometimes a read to a field of a datareader returns a invalid cast exception.
I will give all information possible to understand my situation. I'm working with ASP.NET 3.5
I have a Module that have a function that returns a IDataReader and receives a sql query. something like this
function get_dr(query as String) as IDataReader
dim connection = new SqlClient.SqlConnection("connection string")
connection.open()
dim command = connection.createCommand
command.commandText = query
dim reader = command.executeReader(CommandBehavior.CloseConnection)
return reader
end function
I have a Class with a Shared function that recovers a new dataReader and returns a date. something like this:
public shared function getDate() as Date
using dr = get_dr("SELECT dbo.getDate()")
if dr.read() and dr(0) isnot dbnull.value then
return dr.GetDateTime(0)
end if
end using
end function
when in another code i call the getDate() function, it gives me a call stack like this.
System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_DateTime()
at System.Data.SqlClient.SqlDataReader.GetDateTime(Int32 i)
Why sometimes i'm getting this error? i was thinking this is because that a lot of users is calling this function in conjunction with another functions of my application (those functions eventually uses get_dr too), mixing the data of the dataReader on another executions, but i need to know if im doing something wrong or maybe to do something better.
Notes:
dbo.getDate is a sql function that ALWAYS returns a date.
don't worry about bad writing code, those are only examples but they have the necessary to understand the scenario.
sorry for my bad english
Really thanks in advance.
One possible reason - you declare connection inside of the function that returns DataReader. When you're out of the function that connection goes out of scope. That means that at some unpredictable point (depends on memory usage etc.) Garbage Collector will collect it. If you try to use the DataReader at that point - all bets are off.
One way to solve it is to declare connection outside of function get_dr and pass it there as a parameter. But also seeing that you're returning a single value and if you don't plan to use the reader for multiple values I suggest using ExecuteScalar instead - it will save you a lot of headaches.

Function to check if Input is in column in SQL Server database

Okay, I'm creating an application which requires the user to input there Gamer-Tag during the registration process. Only 'Members' of a group may have access to the program and so I need the application to refuse anyone who's Gamer-Tag is not in the SQL Server database.
I adapted a function I created to log-in with your details and changed it to check if the Gamer-Tag is on the database, but I'm receiving a strange error:
The column 'Gamer_Tag' is not a Member of 'Members_Details' Table.
Please note, that's an error and not what I am wanting it to do. It's saying the column 'Gamer_Tag' isn't in the table, but I know it is! I've checked spelling and spacing and everything's as it should be, so I'm assuming it's something wrong with the code.
The (relevant) register button code:
(Note, RegUserName.Text is the textbox that contains the users Gamer-Tag.
Dim dbManager As New DatabaseManager()
If dbManager.CheckGamerTagisMember(RegUserName.Text) Then
MsgBox("Gamer-Tag Not A Member.")
My.Settings.RegisterCount = 1
My.Settings.Save()
RegisterBTN.Enabled = True
MsgBox("Registration Failed.")
GoTo Ender
Else
MsgBox("Gamer-Tag is A Member.")
GoTo Ender
End If
And the function this is calling:
Public Function CheckGamerTagisMember(ByVal gamertag As String) As Boolean
Connection = New SqlConnection("Data Source =" & My.Settings.ServerIP & ";Initial Catalog=Members_Details;Integrated Security=False;User=" & My.Settings.UserName & ";Password=********;")
Connection.Open()
Dim gamertagDatSet As New DataSet()
usersDataAdapter.FillSchema(gamertagDatSet, SchemaType.Source, "Members_Details")
usersDataAdapter.Fill(gamertagDatSet, "Members_Details")
Dim table As DataTable = gamertagDatSet.Tables("Members_Details")
For i As Integer = 0 To table.Rows.Count - 1
Dim currentUsergt As String = table.Rows(i)("Gamer_Tag").ToString.Trim()
If (currentUsergt = gamertag) Then
gamertagDatSet.Dispose()
Connection.Close()
Return True
End If
Next
gamertagDatSet.Dispose()
Connection.Close()
Return False
End Function
And to prove the column is in the table, here's the table's columns;
I'm new to structuring my code into classes, so I could be 'passing' things around wrongly.
Any help would be much appreciated!
I haven't a clue what the issue is with your code (there's probably something else going on which is not evident in your question).
But I will say that the approach you are taking will not scale well. With each registration, you are downloading the entire table to the program and then scanning through the rows, one by one, looking for an ID.
It would be much easier to write a simple stored procedure to do this for you. You would also get the advantage of using indexes. For example:
CREATE PROCEDURE spGetMembers_ID
#Gamer_Tag varchar(255)
AS
SET NOCOUNT ON;
SELECT Members_ID
FROM Members_Details
WHERE Gamer_Tag = #Gamer_Tag
GO
You can call this stored proc this way:
Dim getMembers_IDCommand As New SqlCommand("TestProcedure", Connection)
getMembers_IDCommand.CommandType = CommandType.StoredProcedure
Dim gamerTagParam As SqlParameter = getMembers_IDCommand.Parameters.Add("#Gamer_Tag", SqlDbType.VarChar, 255)
gamerTagParam.Value = gamertag
SqlDataReader result = getMembers_IDCommand.ExecuteReader();
Dim exists As Boolean = myReader.Read()
result.Close()
Return exists
There, of course, many ways to execute a stored procedure and get the results. Several are documented here. But the point is that a stored procedure is faster, more scalable and generally faster.

How to get a return value from a stored procedure in VB.NET

I have a stored procedure in SQL Server for generating transaction numbers.
Can anyone help me with how to call the Stored Procedure from VB.NET and how will i get the value that is returned from the procedure into the front end.
Regards,
George
I think you want something like this:
Public Sub Foo()
Using sql As New SqlClient.SqlConnection("YourConnection")
sql.Open()
Using cmd As New SqlClient.SqlCommand("YourSPName", sql)
cmd.CommandType = CommandType.StoredProcedure
Dim myReturnValue As String = cmd.ExecuteScalar
End Using
End Using
End Sub
Where myReturnValue will be what ever your output param in SQL is.
What kind of value is it you're returning? Will that value in turn result in another database action?
It might be best to return data instead of a single value.
For example if you were verifying the username and password for a potential login, instead of returning a simple true or false you would return the users information. No information returned means failed login.
This method has the advantage of minimising database requests, something which will have a serious effect if it is a common action.
Personally I've never needed to return a single value.

Please help prevent data layer refactoring of this ODP.NET code and transactions

I am using Oracle 11g client, with ODP.NET. I am trying to add conditional Transaction handling.
Dim ds As New DataSet()
Dim txn As OracleTransaction
Dim _beginTransaction as Bolean = true
Using conn As New OracleConnection(ConnString)
Try
conn.Open()
If _beginTransaction Then
txn = conn.BeginTransaction(IsolationLevel.Serializable)
End If
Dim adapter As OracleDataAdapter = New OracleDataAdapter()
adapter.SelectCommand = New OracleCommand(sSQL, conn)
For i As Integer = 0 To UBound(parameters, 1)
adapter.SelectCommand.Parameters.Add(parameters(i))
Next
adapter.Fill(ds)
If _beginTransaction Then
txn.Commit() //txn is undefined here? why?
End If
Catch e As Exception
txn.Rollback()
End Try
End Using
How do I fix txn being nothing / null? The error is: Variable 'txn' is used before it has been assigned a value. A null reference exception could result at runtime. Links or pointers to solutions would be appreciated also.
Edit: Thanks to RichardOD for pointing out that you can not explicitly declare that a transaction cannot be opend up on stored procedures via ODP.NET. I have verified that this is an issue. BUT We still haven't figured out why the error is occuring. I understand that txn is initially given a value w/in an if statement, but being defined outside of the try/catch block should make that irrelevant.... right? Or is that bad coding?
Assuming _beginTransaction is a boolean have you set it to true before If _beginTransaction Then ?
Also have you committed the previous transaction before starting this one? Oracle can do weird stuff with connection pooling and BeingTransaction.
A long time ago I had a bug similar to this. Have you looked here?
Edit- are you trying to call a .NET stored proc? OracleConnection.BeginTransaction does not support stored procedure calls:
OracleConnection.BeginTransaction is
not allowed for .NET stored procedure
Question: Is it null immediately after being asigned? And if not, when does it become null? If it's null after immediately, it might be the connection pooling stuff. If after getting the adapter from conn or after filling it, then it's even crazier...
But I would try and find out
Oracle does not require a transaction for selecting data. Why do you try open one?
EDIT:
If your vb code is called from oracle (via .net integration) than there is no transaction support as RichardOD wrote. Please clarify the environment.
The sql statement executed is dynamic and given in sSQL. The command is prepared and given to a DataAdapter that fills a DataSet. Than you can only execute SELECT statements. Otherwise there is no result.
OR
Because the parameters are prepared too. You are calling a stored procedure (without telling the the CommandType is StoredProcedure). One of your parameters is a ref cursor parameter which will fetched into the DataSet. Right?
Oracle does not need explicit transactions as sql server does. Oracle starts an implicit transaction with the first dml statement in your session. The sideeffect is, if you did not start an transaction you cannot commit the implicit transaction. I do not know if there is access to implicit transaction via the connection object.