Executenonquery return value - asp.net

I want to perform a search on a table to see if record exists. I do not want to perform insert or update after. I have done this already but somehow I cannot get this to work. On my asp.net page I cannot seem to get any value returned. The error is "input string not in correct format" I ma sure it is obvious but I cannot seem to see it now!
here is my code:
Dim con As New SqlConnection("connstring")
Dim cmd As New SqlCommand("checkname", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New SqlParameter("#d", SqlDbType.Int))
cmd.Parameters("#id").Value = TextBox1.Text
Dim para As New SqlParameter
para.Direction = ParameterDirection.ReturnValue
para.ParameterName = "returnvalue"
cmd.Parameters.Add(para)
con.Open()
cmd.ExecuteNonQuery()
Dim exists As Integer
exists = Convert.ToInt32(cmd.Parameters("returnvalue").Value)
If exists = 1 Then
Label1.Text = "You......"
ElseIf exists = 0 Then
Label1.Text = "You....."
End If
con.Close()
stored procedure:
CREATE PROCEDURE checkname
-- Add the parameters for the stored procedure here
#id int
AS
--This means it exists, return it to ASP and tell us
-- SELECT 'already exists'
IF EXISTS(SELECT * FROM attendees WHERE id = #id)
BEGIN
RETURN 1
END
ELSE
BEGIN
RETURN 0
END

You need to ensure that you are passing an integer.
int intValue;
if(!int.TryParse(TextBox1.Text, out intValue))
{
// Update your page to indicate an error
return;
}
cmd.Parameters.Add(New SqlParameter("id", SqlDbType.Int));
cmd.Parameters("id").Value = intValue;
(Technically you don't need the "#" character when
defining the parameters in the .NET
code.)

You have declared your procedure parameter as #d instead of #id. Also a return parameter cannot be an input parameter. The return value should be an exit code. You most likely want to create an output parameter and set that to 1 or zero inside of your stored procedure.
Edit: to clarify, the return value is generally regarded as an indicator of correct execution. Zero usually means success, where any other numeric value is generally regarded as an error code. That is why I recommended adding an output parameter instead of adding a return value parameter.

ExecuteNonQuery returns the number of rows affected. Therefore the return values that you set in your stored procedure are thrown away and will not be returned by the ExecuteNonQuery method.

ExecuteNonQuery is used to Insert / Delete / Update operations. Not for SELECT, you need either ExecuteScalar or ExecuteReader methods. This link will help you to know how to use output parameters : http://aspdotnet-suresh.blogspot.com/2010/10/introduction-here-i-will-explain-how-to.html

Related

SQL parameters asp.net(vb.net)

Sorry for my bad English.I have a problem in my code:
Dim sq As String = "SELECT username FROM standing WHERE username = #user"
Dim con As New SqlConnection(Sql.ConnectionString)
Dim cmd As New SqlCommand(sq, con)
cmd.Parameters.Add("#user", SqlDbType.VarChar)
cmd.Parameters("#user").Value = "contesttest"
con.Open()
Dim index As Integer = cmd.ExecuteNonQuery
con.Close()
If (index > 0) Then
'Something..
Else
'Something else..
End If
in my code,"contesttest" is exists in Database and returnedrows(index) should be greater than 0.But index is -1 !What's the problem?
my connectionstring is right.
It does not matter if C# or VB.Net
If your username field is an unique index (meaning that you don't have two username with the same value) then your query could be rewritten without using a SqlDataReader
Dim sq As String = "SELECT username FROM standing WHERE username = #user"
Using con SqlConnection(Sql.ConnectionString)
Using cmd As New SqlCommand(sq, con)
cmd.Parameters.Add("#user", SqlDbType.VarChar)
cmd.Parameters("#user").Value = "contesttest"
con.Open()
Dim username = cmd.ExecuteScalar
If userName IsNot Nothing Then
'Something..
Else
'Something else..
End If
End Using
End Using
ExecuteScalar return the first column of the first row retrieved by your command. In the case you column is a unique index/primary key then you have just one row and you return just the username. So if there is something returned then you have found your user
From MSDN;
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
This is not a problem. It is a definition of ExecuteNonQuery method.
Use a Reader of some sort (like a SqlDataReader) to get the number of rows returned from a SELECT statement or ExecuteScalar to get a single returned value. Using ExecuteNonQuery will only return the number of rows affected when used with a SELECT statement.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
Read about it on MSDN.
i guess SqlDbType.VarChar will allow only one character ..you need to pass length also for varchar.
for Example:-
cmd.Parameters.Add("#user", SqlDbType.VarChar,80)

checking for duplicate values before attempting insert (ASP.NET)

I have a form where two fields on the first page of the form make up the primary key. I want to check for duplicate values before attempting to insert the record, since I don't want the user to go all the way through the form only to find out they can't submit it. So I'm trying to check for duplicate values when the user tries to go to the next page of the form. I wasn't quite sure how to do it, and sure enough I'm getting an error. ("Object reference not set to an instance of an object.") The problem is apparently in my if statement, "If myValue.Length > 0 Then", but I'm not sure what needs to be in place of that.
Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
'get values
Dim checkPrefix = txtCoursePrefix.Text
Dim checkNum = txtCourseNum.Text
'db connectivity
Dim myConn As New OleDbConnection
myConn.ConnectionString = AccessDataSource1.ConnectionString
myConn.Open()
'select records
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix='checkPrefix' AND course_number='checkNum'", myConn)
'execute(Command)
Dim myValue As String = mySelect.ExecuteScalar()
'check if record exists
If myValue.Length > 0 Then
CustomValidator1.ErrorMessage = "some exp text"
CustomValidator1.SetFocusOnError = "true"
CustomValidator1.IsValid = "false"
End If
End Sub
Thought I'd post the final solution:
'select records
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
'execute(Command)
Dim myValue = mySelect.ExecuteScalar()
'check if record exists
If myValue IsNot Nothing Then
CustomValidator1.SetFocusOnError = True
args.IsValid = False
End If
This error indicates that the content of myValue variable is null. If it's null you can't use Length property (or any other property for that matter) on it. You have to check for null explicitly:
If myValue IsNot Nothing Then
EDIT 1
Your sql query is wrong. I don't know what would be the right query, as I don't know your database, but I think you intender to write this:
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix=" + checfkPreix + " AND course_number=" + checkNum, myConn)
or something to that effect. You might want to consider using string.Format function for forming the string. And you also need to make sure that there is some kind of protection against SQL Injection, since you form your query from user input. In your case using of OleDbParameter might be appropriate.
Edit 2
You also right to mention that there might be a problem with ExecuteScalar. ExecuteScalar is supposed to return a single value and your select query are returning two (prefix and course_number). Change it so that it returns a single parameter SELECT prefix FROM or simply SELECT 1 FROM and then the rest of the query:
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
Edit 3
You are not setting failed validation properly in your validator.
Add
args.IsValid = False
inside your if statement.
First ExecuteScalar will only return a single value, so in this case you are only going to get the column prefix from the result. Second if there is no match with your query it will return null, so your next length check should account for that scenario:
if String.IsNullOrEmpty(myValue) Then
...
Reference: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
myValue is null if there is no duplicate, so you have to apply .Length only if myValue is not null (which means checking for null only is enough; without .Length)
If Not string.IsNullOrEmpty(myValue) Then
try something like this instead (you will have to adapt it to VB.Net) DBNull is different from Null or Nothing so you have to compare it to both
If myValue <> DBNull and not myvalue is nothing Then

SQL Stored Procedures failing to return values

I am working on a Tag system for a news page designed in ASP.NET. For the system I require a TagExists method to check for tags within the database. The stored procedure I have written is below.
ALTER PROCEDURE [dbo].[Tags_TagExists](
#Tag varchar(50))
AS
BEGIN
If (EXISTS(SELECT * FROM dbo.Tags WHERE LOWER(#Tag) = LOWER(Tag)))
RETURN 1
ELSE
RETURN 0
END
When I call this method however 0 is always returned. I am using the following code to call the method
Public Shared Function TagExists(ByVal name As String) As Boolean
Dim result As Boolean
Using conn As SqlConnection = New SqlConnection(ConnectionString)
Dim cmd As New SqlCommand("Tags_TagExists", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#Tag", name)
conn.Open()
result = Convert.ToBoolean(cmd.ExecuteScalar())
conn.Close()
End Using
Return result
End Function
I have tried switching the procedure to return 0 if the tag exists and 1 if it does not and it still returns 0 despite the exact same testing conditions. I have also returned the actual select query and it has complained of the Tag "news" (my test item) not being an int on execution showing the select itself is definitely properly formed.
If anyone can shed some light on this, Thanks
Michael
It should probably be a function, but here is the stored proc code:
ALTER PROCEDURE [dbo].[Tags_TagExists](
#Tag varchar(50))
AS
BEGIN
If EXISTS(SELECT 1 FROM dbo.Tags WHERE LOWER(#Tag) = LOWER(Tag))
BEGIN
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
END
You're returning from a Stored Procedure, not getting a single scalar value from a SQL statement.
I'm assuming this is a simple example and you have other processing you want to handle inside the Stored Procedure. In that case, using the Stored Procedure and return value is the right way to go. You need to handle the return value from the Stored Procedure in your C# code (Please excuse any syntax errors, my VB.NET is a bit rusty):
Public Shared Function TagExists(ByVal name As String) As Boolean
Dim result As Boolean
Using conn As SqlConnection = New SqlConnection(ConnectionString)
Dim cmd As New SqlCommand("Tags_TagExists", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#Tag", name).
Dim retVal As SqlParameter = _
cmd.Parameters.Add("return_value", SqlDbType.Int)
retval.Direction = ParameterDirection.ReturnValue
conn.Open()
cmd.ExecuteNonQuery()
result = System.Convert.ToBoolean(retval.Value)
conn.Close()
End Using
Return result
End Function
If you're strictly interested in the return value and your Stored Procedure isn't performing any other use, then convert it to a simple select statement (or function). Your use of ExecuteScalar would work in that case.
Please try using SELECT 1 and SELECT 0 instead of RETURN statement
Hope that helps,

IF EXISTS IN STORED PROCEDURE

I am using following storedprocedure
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
Alter PROCEDURE [dbo].[GetUserDetailsByUserID]
(
#UserId varchar(100)
)
AS
BEGIN
IF EXISTS(Select * from Registration where UserId=#UserID)
BEGIN
Select
[Name],
[UserId],
[PermanentAddress],
[TemporaryAddress],
[OfficePhoneNo],
[ResidentialPhoneNo],
[MobileNo],
[Email],
[ContactPerson],
[C_OfficePhoneNo],
[C_ResidentialPhoneNo],
[C_MobileNo],
[C_Email],
[Project],
[TotalAmount]
From
Registration
Where
UserId=#UserId
END
END
I am using following code in vb
Public Function GetUserDetailsByUserID(ByVal strUserId As String) As DataTable
Try
Dim db As Database = DatabaseFactory.CreateDatabase()
Dim DbCommand As DbCommand = _
db.GetStoredProcCommand("GetUserDetailsByUserID")
db.AddInParameter(DbCommand, "#UserId", DbType.String, strUserId)
Return db.ExecuteDataSet(DbCommand).Tables(0)
Catch ex As Exception
Return New DataTable()
End Try
End Function
If details corresponding to userid does not exist in registration table, db.ExecuteDataSet(DbCommand).Tables(0) shows one error as cannot find Table(0). What modification in stoted procedure i hve to make to get rid of this error?
You can simply get rid of the IF EXISTS. When the record doesn't exist, you will get an empty table (which I think is what you want, looking at your sample code)
The procedure will not always return a record set. If there is no record set then Tables will be empty and Tables(0) will fail and return an error. You should just return the selection rather than only selecting if the record exists. Your code can then check for an empty returned record set.
In the VB code, change
Return db.ExecuteDataSet(DbCommand).Tables(0)
to
Dim Ds as DataSet = db.ExecuteDataSet(DbCommand)
If Ds.Tables.Count = 1 Then
Return Ds.Tables(0)
Else
Return New DataTable()
End If
Also, remove the If Exists from the Stored Procedure, since if the row exists, you will force the database to search twice in the table for the record where UserId=#UserID.

DbNull.Value Stored Procedure Parameter?

I have a web service which has a generic function that returns a dataset from results of stored procedures... Some of the stored procedures have optional parameters where the value can be null but not all the time.
Anyhow I am trying to pass in a parameter which has a value of DBNull.Value
and I get this There was an error generating the XML document. back from the web service when doing so
If I leave this parameter out it works fine... but really would like to know why DBNull.Value causes this problem.
I beleive that's becuase a System.DBNull value is a null in database table but a null field in a procedure effectively equates to the null/nothing keyword. Not a database null value. I'm not sure of the technical differences under the hood.
But in your stored proc you can just default it to null and not send the value as you've already done or i believe if you sent null/nothing it would also work.
You can pass a NULL value in the SqlParemeter, but you must do some type conversion to make sure the right null value gets passed.
In this example, there is a parameter called "Count" which is an integer, which gets passed as null:
Using dtResult as New DataTable
Using cn as SqlConnection = New SqlConnection ("ConnectionString")
Using sqlcmd as SqlCommand - New SqlCommand("StoredProceName", cn) with {.CommandType=CommandType.StoredProcedure}
Dim sp As SqlParameter
sp = sqlcmd.Parameters.Add("#Count", SqlDbType.Int)
sp.value = CType(Nothing, SqlTypes.SqlInt32)
Using myDR as SqlDataReader = sqlcmd.ExecuteReader
dtResult.Load(myDR)
end using
return dtResult
End Using ' For sqlcmd
cn.Close() ' Close the connection
end using ' For cn
end using ' For dtResult

Resources