Executing stored procedure in vb.net - vb.net

I need to execute a stored function in oracle or sql through vb.net.
I created a command object. Depending on the database type(oracle or SQL) i am preparing the
Command text as Select functionName(?,?,?,?,?,?,?,?) from dual; (For Oracle)
Adding the parameter values of the function
Now performing the ExecuteScalar which is not working saying invalid parameter.
This works with ODBC connection string. But ODBC doesn't with 64bit.
My Requirement: Code should execute a user defined stored procedure by taking the values at runtime.
Thanks
Rupesh

Your command text should be just the Stored procedure name without a select, and make sure you set the command type to stored procedure. Check out this link for example:
http://support.microsoft.com/kb/321718
Oracle:
Dim cmd As New OracleCommand
cmd.Connection = conn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "OracleSP"
Dim p1 As OracleParameter
Dim p2 As OracleParameter
p1 = cmd.Parameters.Add("Param1", OracleType.NVarChar)
p1.Value = "Value1"
p2 = cmd.Parameters.Add("Param2", OracleType.Double)
p2.Value = 10
cmd.ExecuteNonQuery()
SQL Server:
cmd.Connection = conn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "SqlSP"
cmd.Parameters.Add("#Param1", SqlDbType.Int)
cmd.ExecuteNonQuery()
I am not sure about Oracle as I haven't done it (I think it should work) but with Sql server you can use:
SqlCommandBuilder.DeriveParameters(cmd)
to populate the SqlParametersCollection on the command, instead of setting them like I did.
MSDN documentation
After that you can loop thru them and set your values as necessary.

Related

VB .NET Paramaterized SQL call not correctly parsing IN clause arguments [duplicate]

This question already has answers here:
Parameterize an SQL IN clause
(41 answers)
Closed 6 years ago.
So I am currently working on a project where I am looking to retrieve all data from a table matching a modifyable list on the screen. Here is a sample of the code that I am using to make the call
Public Sub GetAnimals(ByReg selectedTypes As String)
Dim strSql As String
Dim pselectedTypes As SqlClient.SqlParameter = New SqlClient.SqlParameter("#pselectedTypes", selectedTypes)
Dim strDBConnection As String = DBConnection.GetConnection.ConnectionString
Dim rs As DataSet = new DataSet
strSql = "SELECT * FROM PetInformation WHERE AnimalType IN (#pselectedTypes)"
Using sqlConn As SqlClient.SqlConnection = New SqlClient.SqlConnection(strDBConnection)
sqlConn.Open()
Using sqlcmd As SqlClient.SqlCommand = New SqlClient.SqlCommand
With sqlcmd
.Connection = sqlConn
.CommandTimeout = DBConnection.DLLTimeout
.CommandType = CommandType.Text
.CommandText = strSql
.Parameters.Add(pselectedTypes)
Using sqlda As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter(sqlcmd)
sqlda.Fill(rs)
End Using
End with
End Using
End Using
' Data Calculations
End Sub
This then makes the SQL query look something like this. For this example I'm using my list of animals as just cats and dogs.
exec sp_executesql N'SELECT * FROM PetInformation WHERE AnimalType IN (#pselectedTypes)',N'#pselectedTypes nvarchar(22),#pselectedTypes='''cat'',''dog'''
So everything looks all fine and dandy but when I go to run it and execute it I don't get any results back. If I change the sql to look like either one of these I get data back, but since this SQL is generated that's not really an option w/o switching away from parameterized sql, which I don't want to do.
exec sp_executesql N'SELECT * FROM PetInformation WHERE AnimalType IN (''cat'',''dog'')',N'#pselectedTypes nvarchar(22),#pselectedTypes='''cat'',''dog'''
or
SELECT * FROM PetInformation WHERE AnimalType IN ('cat','dog')
Any suggestions or ideas?
As far as I know, no db libraries allow parameterizing lists like you are trying. In those situations, you need to build your parameter list and query dynamically based on the number of elements in your list.

Something is wrong with the code or the stored procedure

To start I'll tell you this. The next question is tricky for me, but... This Stored procedures is used in two different databases. Both have the same data, let's call them older and newer.
In the older the stored procedure works fine and I even get the return. But in the Newer doesn't happen the same.
ALTER PROCEDURE dbo.actual_user
#user char(15)
AS
SELECT
US.Usercode, US.UsercodeSQL, US.LastName, US.Name, US.Nivel,
CONVERT(int, US.Timestamp) TS,
S.DateChanged, S.TolPSW, S.LoginsTotals, S.LoginsUsed,
S.InitialDate, S.EndDate
FROM
System_Users US
INNER JOIN
Session_Users S ON US.UssercodeSQL = S.UssercodeSQL
WHERE
US.UsercodeSQL = user_id(#usuario)
AND S.UsercodeSQL = user_id(#usuario)
When I run an EXEC like this (by this way works in both databases):
exec actual_user 'telc\u124453'
I get this output:
Usercode UsercodeSQL LastName Name Nivel TS DateChanged TolPSW LoginsTotals LoginsUsed InitialDate EndDate
----------------------------- ----------- ------------------------------ ------------------------------ ------ ----------- ----------------------- --------------- ------------- ------------ ----------------------- -----------------------
FESPE 15 Brond Manny NULL 16838419 2007-04-16 16:57:00 30 10 0 NULL NULL
But the code I'm using doesn't work in the newer database. It's just like this.
Here is my new code. It works in the older DB but in the newer doesn't. May the version of SqlServer is not working cause of user_id from the Stored Procedure, I don't know.
Public Function UsuarioActual(ByVal datoUsuario As String) As DSUsuario.UsuarioActualRow
Dim ds As New DSUsuario
Dim dt As New DataTable
Dim sqlConn As SqlConnection = New SqlConnection()
Dim sqlAdp As SqlDataAdapter
Try
sqlConn = MyBase.GetConnection
Dim command As New SqlCommand("Usuario_Actual", sqlConn)
command.CommandType = CommandType.StoredProcedure
command.Parameters.AddWithValue("#usuario", datoUsuario)
sqlAdp = New SqlDataAdapter(command)
sqlAdp.Fill(dt)
Catch ex As Exception
proc = "UsuarioActual"
ERROR
epn = New FactEspExceptions(ex, TipoExcepcion.ErrorBD, proc, Nothing, ex.Message)
epn = New FactEspExceptions(ex, TipoExcepcion.ErrorBD, proc)
epn.AuditarError()
Throw epn
Finally
sqlConn.Close()
sqlConn = Nothing
End Try
If ds.UsuarioActual.Rows.Count > 0 Then
Return ds.UsuarioActual.Rows(0)
Else
Return Nothing
End If
End Function`
Edit 1:
When the code runs, on the Older DB it works. But when it runs on the Newer DB, it doesn't. I don't know if it's about permissions, execSP, or something is missing. So in my point of view, i can say the problem is on the SP.
Edit 2:
Running from the code I get no output.
This is the error running from an EXEC on both DB.
Procedure 'actual_user' has no parameters and arguments were supplied
Edit 3: Code updated.
Dim comando As String = "EXEC actual_user"
Try
sqlConn = MyBase.GetConnection
Dim com As SqlCommand = New SqlCommand()
com.CommandText = comando
com.Connection = sqlConn
com.CommandType = CommandType.StoredProcedure
com.Parameters.AddWithValue("#User", usuTelecom)
The reason you're getting the error is that no parameters are being passed. This will pass the parameter in question.
The one thing I don't understand in your stored procedure is why there's a #usuario variable that doesn't seem to be declared. I'm thinking that you stripped some stuff out, though.

using IN condtion in SQL CE

How we can we pass list of values as parameters in SQLCE?
using the below code works (when directly passing list of values in query)
SqlCeCommand cmd = string.Format("Select VMID from Booking where (VMID in ({0})",
selectedVMs );
SqlCeManager.OpenSqlConnection();//my custom code to open sql connection
sqlCmd = new SqlCeCommand(cmd, SqlCeManager.sqlConn);
But the below code does not work ( when passing the list of values using the parameters).
SqlCeCommand cmd = "Select VMID from Booking where (VMID in (#VMIDs))";
SqlCeManager.OpenSqlConnection();//my custom code to open sql connection
sqlCmd.Parameters.Add("#VMIDs", string.Join(",", selectedVMs));
sqlCmd = new SqlCeCommand(cmd, SqlCeManager.sqlConn);
The error i get is "#IDs : 8,7 - Input string was not in a correct format."
What am i missing here ?

How do I get SqlCommand ExecuteNonQuery result?

In order to check if specific user is db_owner, i excute the following query:
"select is_rolemember('db_owner', '" & p_userName & "')"
using the SqlCommand ExecuteNonQuery method.
How do I get the query result?
Here is my code:
Dim com As SqlCommand = New SqlCommand(sql, m_connection)
com.ExecuteNonQuery()
sql is the query, and m_connection is the connectionString.
You can use ExecuteScalar
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
like Lucero said.
EX:
cmd.CommandText = "SELECT COUNT(*) FROM dbo.region";
Int32 count = (Int32) cmd.ExecuteScalar();
Returning the Int.
While everyone has given the answer I would like to point out that your sql is vulnerable to injection if p_userName can in anyway be influenced by a client.
Also note that is_rolemember can return Null (See Microsoft Reference)
Below is an implementation that is not vulnerable to Sql Injection (it uses parameterized sql).
Dim com As SqlCommand = New SqlCommand("select is_rolemember('db_owner', #UserName)", m_connection)
com.Parameters. AddWithValue("#UserName", p_userName)
Dim result As Object = com.ExecuteScalar
If (result = DBNull.Value) Then
Throw New Exception("database_principal or role is not valid, or you do not have permission to view the role membership.")
Else
Return CType(result,Int32)
End If
You need to use ExecuteScalar, not ExecuteNonQuery.

Is it possible to insert an entire VB.NET DataTable into a SQL Server at once

I have a SQLClient.DataSet in VB.NET, and I want to insert the entire thing into a SQL Server table without having to do the following:
For Each dr as Datarow in MyDataset
Dim sc As New SqlCommand("INSERT INTO MyNewTable " & _
"VALUES (#column1, #column2)", MyDBConnection)
sc.Parameters.AddWithValue("#column1", dr.Item(0))
sc.Parameters.AddWithValue("#column2", dr.Item(1))
sc.ExecuteNonQuery()
Next
Since I've got close to a million rows (all pretty skinny, so it's not much space), I obviously don't want to run this loop and generate a million INSERT statements.
I know that one option is to use a linked server when I initially fetch the data, since it's coming from another SQL Server, and just have it to the INSERT from there. However, if I already have the data in my application, is there a more efficient way to bulk insert it? Can I somehow pass the DataTable as a parameter to SQL Server and have it sort it out and insert the rows?
try with SqlBulkCopy
With SQL Server 2008 you can use Table-Valued Parameters:
Dim sc As New SqlCommand(
"INSERT INTO MyNewTable (field1, field2,...)"&
"SELECT field1, field2,... FROM #MyTable;", MyDBConnection)
sc.Parameters.AddWithValue("#MyTable", MyDataset)
sc.ExecuteNonQuery()
Use the SqlDataAdapter's InsertCommand to define your Insert query. Then call the DataAdapter's Update Method with your dataset as a parameter to have it push the data.
Something like:
Dim DA As SqlDataAdapter = New SqlDataAdapter
Dim Parm As New SqlParameter
DA.InsertCommand = New SqlCommand("Insert Into tbl1(fld0, fld1, fld2) Values(#fld0, #fld1, #fld2)", conn)
Parm = DA.InsertCommand.Parameters.Add(New SqlParameter ("#fld0", NVarChar, 50, "fld0"))
Parm = sqlDA.InsertCommand.Parameters.Add(New SqlParameter ("#fld1", SqlDbType.NVarChar, 50, "fld1"))
Parm = sqlDA.InsertCommand.Parameters.Add(New SqlParameter ("#fld2", SqlDbType.NVarChar, 50, "fld2"))
DA.Update(dataset1, "tbl1")
You could call .WriteXML() on the DataSet and dump that into the database in one insert.
A way simplier way is to use a table adapter. Then you can use the Fill method to give a datatable as argument :
Dim oStronglyTypedTable As StronglyTypedDataTable = GetTable() 'A custom function that creates your table from wherever you want)
If Not oStronglyTypedTable Is Nothing Then
Using oAdapter As New StronglyTypedTableAdapter
Dim res As Integer = oAdapter.Update(oStronglyTypedTable)
MsgBox(res & " rows have been updated.")
End Using
End If
Do not forget to change your Database "Copy to Output Directory" property to "Do net copy" and set your connection string properly...