I have a Stored Procedure which when run on SQLServer takes 1 second to run, yet in my VB.Net code it takes nearly 20 seconds. It takes a long time on the line:
Adapter.Fill(ds,"TimeTable")
Am I doing something wrong for it to take so long?
My code snippet is below:
SQLConn = New SqlConnection(SQLDConnString)
cmd = New SqlCommand("SPNAME", SQLConn)
cmd.CommandType = CommandType.StoredProcedure
SQLConn.Open()
cmd.Parameters.AddWithValue("#p1", p1)
cmd.Parameters.AddWithValue("#p2", p2)
cmd.Parameters.AddWithValue("#p3", p3)
cmd.Parameters.AddWithValue("#p4", p4)
adapter.SelectCommand = cmd
adapter.Fill(ds, "TimeTable")
DataGridView1.DataSource = ds.Tables("TimeTable")
SQLConn.Close()
If your datagridview property for column and row height/width is set to auto, it can take a lot of time to finish the procedure. I had this happen once, where a stored procedure took an abnormally large amount of time and it ended up being that property that was causing it to stall.
I seemed to find a fix to this by declaring local variables in my SP and then assigning my Parameters to these variables.
Something to do with parameter sniffing.
Related
First time poster - medium length reader. I'm an entry level programmer, currently working on passing a SQL Stored Procedure some information that might contain a single quote (').
In the past, we've attempted to just use a .Replace("'","''") when passing this information, but recently, we've run into some issues with returning data and having the set changes and replaces in about 20 places (corporate, woo!).
I've been looking at using SQL Parameters to not have to worry about these buggers: ', but cannot see/understand the difference in my below code. The first block was the original working version. The second is my attempt at introducing #paras.
SQL is being passed through ByVal as a String
Previous Code:
Dim dbConnection As New SqlConnection(ConnectionString)
Dim dbCommand As New SqlCommand(SQL, dbConnection)
MsgBox(dbCommand.CommandText.ToString) //Returns proper procedure/paras
dbCommand.CommandTimeout = CommandTimeout
dbConnection.Open()
dbCommand.ExecuteNonQuery()
Code with SQL Parameters:
Dim dbConnection As New SqlConnection(ConnectionString)
Dim dbCommand As New SqlCommand("#SQL", dbConnection)
dbCommand.Parameters.Add("#SQL", SqlDbType.VarChar).Value = SQL
MsgBox(dbCommand.CommandText.ToString) //Returns "#SQL"
dbCommand.CommandTimeout = CommandTimeout
dbConnection.Open()
dbCommand.ExecuteNonQuery()
I feel the second block should be returning the same information. A MsgBox from the first block will return the proper SQL. The second however, just returns "#SQL", not the SQL value it seems to assign.
Is there a special way of refreshing the SQL Command?
Am I unable to only declare #SQL and replace it later?
Took a peek around MSDN as well as quite a few searches, leading me here already, with no luck.
Here is how you would make this a parameterized call. Kudos for taking the effort to protect against sql injection!!!
dbCommand.CommandText = "LoginPassword"
dbCommand.CommandType = CommandType.StoredProcedure
dbCommand.Parameters.Add("#userID", SqlDbType.VarChar, 30).Value = userID
dbCommand.Parameters.Add("#Password", SqlDbType.VarChar, 30).Value = password
dbCommand.ExecuteNonQuery()
One thing you need to make sure you do is when you use parameters you should always specify the precision or length. I don't know what yours should be in this case so you will need to adjust as required.
--please forgive me if there is a syntax error. I work with C# but I think I got this correct for vb.net
This seems so simple, but I can't resolve the error
Procedure or function 'test' expects parameter '#id', which was not supplied.
I have tried a dataadapter instead of the reader, tried the {call test (?)} syntax, and several variants on how to add the parameter.
CREATE PROCEDURE [dbo].test (#id int)
AS
BEGIN
select * from tmptable where id=#id
END
Using conn = New OdbcConnection(connstring)
conn.Open()
Dim cmd As OdbcCommand = New OdbcCommand("test", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#id", 6)
Dim reader As OdbcDataReader = cmd.ExecuteReader()
reader.Close()
conn.Close()
End Using
Try dropping the # - so AddWithValue("id",6) instead. I usually explicitly create the parameter and add it to the collection, and when I do I drop the # sign from the parameter name.
Also, I'll modify your code to look like how I usually use it and edit it into my post in a few minutes, if dropping the # doesn't work you can try my style, maybe there are some subtle differences.
EDIT: Oops, my bad, I use the explicitly defined parameters with SQLcommands, not ODBC commands! You can try leaving out the #, but I don't have a working example I can share with you, sorry :-(
EDIT 2: OK, I don't have an example, but Microsoft has one that looks a lot more like how I call my stored procedures using SQLCommands, see
http://msdn.microsoft.com/en-us/library/system.data.odbc.odbcparametercollection%28v=vs.90%29.aspx
Basically, I think your code would look like
Using conn = New OdbcConnection(connstring)
conn.Open()
Dim cmd As OdbcCommand = New OdbcCommand("{ call test(?) }", conn)
cmd.CommandType = CommandType.StoredProcedure
' replace this with the following cmd.Parameters.AddWithValue("#id", 6) '
Dim ParamID As New OdbcParameter()
ParamID.DbType = DbType.Int32
ParamID.Value = 6
cmd.Parameters.Add(ParamID)
' end replace '
Dim reader As OdbcDataReader = cmd.ExecuteReader()
reader.Close()
conn.Close()
End Using
And you should also be aware that some ODBC drivers are not good at getting recordsets back from stored procedures. I use SmallTalk to query DB2 through ODBC, and I can get a recordset back from a function, but not from a stored procedure. You may be encountering a similar limitation. What database are you using?
I am a complete beginner to .net and am confused at some basic things. Please help.
First of all the table I create and populate (by right clicking tables in server explorer) disappear once I restart the computer. how do I keep them.
Is there any better place/interface to type SQL queries in vb.net than the command prompt.
In the following code:
Dim cn As SqlConnection = New SqlConnection(strConnection)
cn.Open( )
' Create a data adapter object and set its SELECT command.
Dim strSelect As String = _
"SELECT * FROM Categories"
Dim da As SqlDataAdapter = New SqlDataAdapter(strSelect, cn)
' Load a data set.
Dim ds As DataSet = New DataSet( )
da.Fill(ds, "Categories")
This far the code runs fine but just to gain better understanding, I would like to ask that
while data from SQL Server database was saved into da in accordance to the query, why do we need to save/transfer it in the dataset object ds.
Is there any additional benefit of SqlCommand over SqlDataAdapter besides speed?
Dim autogen As New SqlCommandBuilder(da)
Dim dt As DataTable = ds.Tables("Categories")
' Modify one of the records.
Dim row As DataRow = dt.Select("CategoryName = 'Dairy Products'")(0)
row("Description") = "Milk and stuff"
gives an error when I use it with
da.Update(ds, "Categories")
regarding dt.select not returning any value.
What is the way out?
to answer your questions :
The tables you create with the server explorer are IN MEMORY. Same goes for dataset, they are in-memory representation of your table. As for your 2nd example, the DS you use isnt filled when you try to get the DT. hence why the DT is empty.
If your starting, I would suggest you go look into Linq-to-Sql (http://msdn.microsoft.com/en-us/library/bb425822.aspx) for a more up-to-date way of doing sql in .net ( I think its 4.0 framework)
As for the 2nd point, I'd say normally you should use store procedure for most of your sql commands .. the sqlcommand is use like this
Try
Cmd = New SqlClient.SqlCommand("st_InventoryStatus_Or_AnyStoreProcName_Or_ASqlQuery")
Cmd.CommandTimeout = 300 'not really needed'
Cmd.CommandType = CommandType.StoredProcedure 'you can type CommandType.Text here to use directly your "Select * from Category"'
Cmd.Parameters.Clear() 'just to be sure its empty, its not mandatory'
Cmd.Parameters.Add("#idCategory", SqlDbType.Int).Value = myCategory.Id 'here are the parameters of your store proc, or of your query ("select * from Category where Category.id = #Id")'
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Information)
End Try
I got an issue that I am completely stumped on.
Part of my application calls a Stored Proc using SQLConnection/SQLCommand. I'm hitting a SQL 2005 database and I am able to make the connection and execute the SP just fine. The problem is it periodically executes the SP multiple times; some times twice, some times three times.
This is basically how I execute the SP...
Dim conString As String = "<Typical Connection String>"
Dim cn As SqlConnection = new SqlConnection(conString)
Dim cmd As SqlCommand = New SqlCommand("dbo.JobStoredProc", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#Val", SqlDbType.VarChar, 12).Value = "Test Value"
cn.Open()
Dim queryResult As Integer = cmd.ExecuteNonQuery
cn.Close()
cn.Dispose()
I can't figure out why sometimes it executes only once, but other times it executes multiple times. Is there something I'm missing? Is there a better way to go about executing the SP?
Thank you very much in advance!
As it turns out it was because I had two of the same File Watchers looking at the same directory. This was causing the above function to fire twice at the exact same time.
I'm writing small VB.Net app which should build reports based on data gathered from some external MDB-files (Access 2007). It was planned that this app will use parametrized SQL queries to collect data. One of the parameters for these queries is path to the external MDB-file.
Here goes sample code:
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=C:\Temp\Temp.mdb;")
conn.Open()
Dim cmd As New OleDbCommand()
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT * INTO Trend FROM TI IN '?' WHERE TI.Id=?;"
With cmd.Parameters
.Add("#p1", OleDbType.VarChar).Value = "C:\Temp\Source.mdb"
.Add("#p2", OleDbType.Integer).Value = 5
End With
cmd.ExecuteNonQuery()
conn.Close()
Looks simple but it doesn't works. After launch my app throws following exception - System.Data.OleDb.OleDbException: Disk or network error.
Have spent a whole day to make it work with no success. What have I done wrong?
This is a comment that others have suggested is the answer to the question:
Nothing in an Access/Jet/ACE FROM clause is parameterizable (unless it's inside a subquery, of course).
With Access/Jet/ACE your only choice is to use some other method to write the FROM clause on-the-fly.