I am building an application that requires me to query an AS400 database up to 100 times per single use.
I have functions for each of the queries right now written in the following structure.
Option Explicit On
Shared Function query1()
Dim conn as New ADODB.Connection
Dim recordSet1 as New ADODB.RecordSet
conn.open("databaseName")
recordSet1.Open("Select * From Table",conn)
Return someValue
End Function
My application runs pretty slow, around 30-40 seconds. I've done some performance profiling using the tools built into Visual Studio 2013 and noticed that repeatedly opening connections to a database is taking up a significant portion of time.
My question is, can I set a global connection variable at the top level of my routine so that I only have to open the connection once, and close it once the routine is finished with all the queries? Do you think that this would significantly speed up my application?
Something like the following:
Option Explicit On
Global conn as ADODB.Connection
conn.open(DSN = "database")
Shared Function query1(ByVal conn)
Dim recordSet1 as New ADODB.RecordSet
recordSet1.Open("Select * From Table",conn)
Return someValue
End Function
Thanks in advance for your help !
Related
Dim cat As New Catalog()
Dim con As New OleDbConnection()
Dim cmd As New OleDbCommand
Dim ds1 As New DataSet
Dim conn As ADODB.Connection
' Open the Access database.
conn = New Connection
conn.ConnectionString =
"Provider=Microsoft.Jet.OLEDB.4.0;" &
"Data Source=" + openExcel + "\Test" + ".mdb; Persist Security Info=False"
con.ConnectionString =
"Provider=Microsoft.Jet.OLEDB.4.0;" &
"Data Source=" + openExcel + "\Test" + ".mdb; Persist Security Info=False"
conn.Open()
xlWorkSheet1.Columns(5).Insert
Dim cellValue As String = ""
Dim newValue As String = ""
Dim sh1 As String = ""
Dim qty As String = ""
Dim matchText As String = ""
Dim sql As String = ""
con.Open()
sh1 = LTrim$(xlWorkSheet1.Cells(i, 1).Text)
sql = "SELECT Num_ber, Q_ty FROM good WHERE Na_me LIKE 'staff%' And Ty_pe = 'ORD'"
Dim cmd As New OleDbCommand(sql, con)
Dim myReader As OleDbDataReader = cmd.ExecuteReader()
conn.Execute(sql)
myReader = cmd.ExecuteReader() ' HERE'S THE PROBLEM
xlWorkSheet1.Cells(1, 5) = myReader.GetString(0)
xlWorkSheet1.Cells(1, 11) = myReader.GetString(1)
myReader.Close()
conn.Close()
conn = Nothing
**I wanted to retrieve a specific value from mdb and then write it to excel.
Here's my code, I got this error so many times and I can't find it out. Can anybody help me? Thanks.**
[1]: https://i.stack.imgur.com/6Fuvg.png
Ok, you first have to decide when usng .net what "provider" you are going to use, AND THEN decide what kind of data objects you want to use.
You can use a oracle provider, a sql server provider, or in this case, since we using Access, then we can use EITHER oleDB, or ODBC. Either choice is fine. Most use oleDB providers for Access, but often ODBC is a good choice, especially if down the road you plane to swap out Access for say SQL server.
What the above means in plain English?
You don't want to adopt the external ADODB code and library. That code is NOT .net, and thus you REALLY but REALLY do not want to write your .net code that way. ADODB was written LONG before .net, and is what we call un-managed code (non .net). I strong, but strong suggest you do NOT add a reference to ADODB to your project, and I beyond strong recommend you avoid introduction of a non .net library for doing this!!! We certainly can adopt the oleDB provider in .net, but we will NOT have a direct reference to JET/ACE (the access database engine) in our applcation. As noted, there are some exceptions to this suggesting, but they don't apply to you and here.
Next up:
The design pattern in .net is to create the connection, get the data, and CLOSE the connection. This "pattern" will then be 100% sure that the data base is always closed, and you NEVER have to worry about if the connection is open, closed, or even if you forgot to close the connection!!! So, do this correct, and some "open" connection will never bite you, or will you have to worry about this issue.
You can in some operations keep the connection open for performance, but lets learn to walk before we run so to speak.
next up:
We certainly do NOT want to place and have connection strings all over in our code. Not only is this going to wear out your keyboard, but if you ever need to change the connection, then you going to have to hunt down all that code.
Best to let Visual Studio save that connection in ONE location, and MORE important MANAGE this for you!!!
Next up:
Do you ONLY need to work with mdb files, or do you plan/need to work with accDB files? This is a HUGE issue, and one that you cannot ignore.
next up:
Are you going to use the x32 bit version of the Access database system, or the x64 bit version?
Since your example posted code uses JET (access data engine for mdb files ONLY x32 bit version)?
Then this ALSO means you MUST (and I repeat MUST) force your .net project to run as x32 bits. You cannot use "any cpu", and you cannot use x64 bits, you MUST choose x86 bit size for your .net project. Failure to do so will result in the project not working.
Ok, with the above information?
First up, force/set/be 100% sure your project is set to run as x32 bits.
That setting is this one:
and remove the reference you have to ADO if you created one.
Ok,
next up:
Create the connection to the database.
Project ->properties.
This here:
And then:
and then
Now, you can browse, and select the access mdb file.
But, you MUST not skip the next step - you have to choose JET (older, mdb files), or choose the newer ACE (for accDB format files).
So, this:
now this:
As noted, you choose JET or ACE here.
now, we have this and you can use test connection.
BUT BE VERY careful!!!!
If you are using vs2022, then keep in mind vs2022 is the FIRST version of VS that is now x64 bits. As a result, vs can't pass the test connection!!! Your connection is in fact ok, but will fail with vs2022.
If you using a previous version of VS (before 2022), then the test connection button should work. and you see this:
Ok, now that we have a valid working conneciton setup, we can now write code, and we will NOT use ADODB!!!!
The typical code pattern to read and load a data table (like a access VBA recordset) will be like this:
Now, I became RATHER tired of writing that same using block over and over. So, in a global module, I have this code now:
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New OleDbConnection(My.Settings.AccessDB)
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
So, now with the above handy dandy helper routine?
Your code becomes this:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim Sql As String =
"SELECT Num_ber, Q_ty FROM good WHERE Na_me LIKE 'staff%' And Ty_pe = 'ORD'"
Dim rstData As DataTable = MyRst(Sql)
Debug.Print("Na_me is " & rstData.Rows(0).Item("Na_me"))
End Sub
Or, display all return rows from that data table
Debug.Print("Na_me is " & rstData.Rows(0).Item("Na_me"))
For Each OneRow As DataRow In rstData.Rows
Debug.Print("na_me = " & OneRow("Na_me"))
Next
So, you really don't need (or want) a reader anyway. Just load the results into a nice clean, easy to use data table, and from that you can loop the table, grab rows, or do whatever you want.
I need a method that will let me keep my MSaccess database open throughout the application operation instead of opening and closing everytime i enter data.
Currently Dim provider As String Dim dataFile As String Dim connString As String Dim myConnection As OleDbConnection = New OleDbConnection Dim cmd As New OleDbCommand
is public declared in each form . And the following is declared on private class
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
dataFile = "C:\Program Files (x86)\SACCO\SACCO_DB.accdb"
connString = provider & dataFile
myConnection.Open()
Dim str As String
str = "INSERT INTO STAFF([ID_NO],[FULL_NAME],[EMAIL],[PASSWORD]) Values(?,?,?,?)"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
This makes my application slower. Kindly, may someone guide me on how i will keep the database open on startup and closed on exit.
yes, this is a long time known issue - and we see near weekly postings about how LARGE delays can occur when opening the database. So for that 20+ years on a NEAR DAILY basis, from Access Front ends to back ends, the solution has been to force + keep a persistent connection. I can make a long post about how and why this occurs, but it has to do with the windows file system - and thus a open of the file, and Access attempting to open exclusive as it attempts to flip the use of the file into high speed single user mode can cause REALLY large delays. As noted, force and to keep the connection open is the near daily advice we see here for close to 20 years.
So, ok, we now using vb.net?
Simply declare a global var in a standard code module as public. Then in your startup code, you can do 1 of two things:
Open the database object - that means you don't have to know ahead of time to "pick" a particlar table to open.
eg this:
Imports System.Data.OleDb
Module MyGlobalCode
Public gDBCon As OleDbConnection ' global connection object
Public Sub GlobalOpenDatabase()
gDBCon = New OleDbConnection(My.Settings.TESTAce)
gDBCon.Open
End Sub
Public Sub GlobalCloseDatabase()
gDBCon.Close()
End Sub
End Module
So, now in any and all code? You use the above gDBCon and you:
Don't have to create a new connection object over and over.
You eliminate this LONG time known slow opening issue.
Now, it not clear why this big delay does NOT occur on some networks and setup - but, if it is occurring, then the above will show spectacular improvements in performance. Often the issue is even virus scanning software, and sometimes it seems to do with Active Directory. And other times, it has to do with VERY slow file creating times (each time you open the database, a ".ldb" file is also created - the time to create this file can be quite long on some systems - again a forced open connection will eliminate your software speeds being limited by external forces such as AD, or virus software, or a good number of other issues that causes this issue.
I am using Windows 7 Professional on a 64-bit Operating System. I am using VBA in Excel and a MySQL ODBC 5.2ANSI Driver connection in SysWOW64 to connect and run queries in a MySQL Workbench 6.3 database. My macro runs a series of queries. It was working fine until the other day when some of the queries stopped working. I print every query, and when I manually copy and paste the query into the MySQL Workbench database, the query runs fine; the data are definitely there. More and more queries have stopped working as time has gone on.
I.E. The first day with issues, a couple queries returned no results. The macro runs about 30 queries. Now, about 7 of the queries do not work.
I do not understand why some queries return results but not others. When I debug, I see the ADODB.Connection is connecting, but the record set is erroring out when attempting to run the query.
Here is what the code looks like:
Sub Test()
Dim myODBC As String
Dim ConnectionString As String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim SQL As String, SQL_ML As String
Dim Var as Double
ConnectionString = “Connection String”
SQL = “SQL String”
Var = MyFunction(SQL, ConnectionString)
‘ Different variable names are used within the function for the connection
'and record set
‘There are 4 functions in this fashion. Only 1 is erroring out at the
'moment!
Dim rng_ML As Range
Set rng_ML = Application.Range("rng_ML")
Dim ML_Matrix() As Double
ReDim ML_Matrix(1, rng_ML.Columns.count)
For i = 1 To UBound(ML_Matrix, 2)
SQL_ML = SQL & rng_ML(1, i)
Set rs = conn.Execute(SQL_ML) ‘This is where it is SOMETIMES erroring out.
rs.MoveFirst
ws.Cells(Row, 1 + i).CopyFromRecordset rs
Next i
End Sub`
Again, this code has worked for months and is now slowly breaking.
Has anyone heard of this before?
Add the following check:
If rs.RecordCount > 0 Then
rs.MoveFirst
ws.Cells(Row, 1 + i).CopyFromRecordset rs
End If
I cannot see where you open the connection but I assume you do it before executing the SQL statements.
Please post the error description, otherwise we can just guess...
I'm using ADODB in Excel 2007 VBA to connect to a Teradata 14.0 server using the Teradata ODBC 15.0 driver. Everything works as expected, except for when I submit very large queries through ADODB.Recordset.Open.
Sporadically, when I attempt recordset.open with a query that is 5000+ characters it throws ODBC Driver does not support the requested properties Error -2147217887.
The error appears after what seems like a set amount of time (30 seconds or so) when I don't get a loaded recordset object back.
The code is straightforward:
Sub getData()
Dim strSQL As String
Dim scRS As ADODB.Recordset
Dim adoConn As ADODB.Connection
strSQL = "Very Large SQL"
'open the connection
Set adoConn = New ADODB.Connection
On Error GoTo adoExit
adoConn.Open "SessionMode=Teradata;Driver=Teradata;DBCName=<SERVERIP>;Database=<DATABASE>;CharSet=UTF16;Uid=<USERID>;Pwd=<PASSWORD>"
'get the data
Set scRS = New ADODB.Recordset
scRS.Open strSQL, adoConn, adOpenKeyset, adLockOptimistic
...
End Sub
Edited to add: I've tried variations of nearly anything that sounded like it might affect packet sizes/timeouts/character sets (which I thought might affect total bytes)/etc in the connection string using http://www.info.teradata.com/htmlpubs/DB_TTU_13_10/index.html#page/Connectivity/B035_2509_071A/2509ch03.05.06.html as a guide. And still I get sporadic timeouts.
Had the same problem while trying to run a composite query.
Try to add: ;QueryTimeout=0 at the end of your connection string (the one that follows adoConn.Open)
I have been searching for a couple hours, and found several questions, but none of them really explained this in a way I can understand.
I'm programming a game similar to Rock Paper Sissors, except with many more selections, and the possiblity of a tie. I had originally hardcoded all of the possible outcomes, then decided to try a database so I can learn and practice sql as well.
Problem is, I can't figure out for the life of me how to connect to my local database, now that I have set it up and filled it through Visual Studio 2010. I can connect to it through Server Explorer just fine, and I can see it in Solution Explorer. I've tried several things, along the lines of:
Private sqlConn As New SqlConnection("Data Source=(local)|DataDirectory|\Outcomes.sdf;database=Outcomes;Integrated Security=true")
Private sqlConn As New SqlConnection("Data Source=.\SQLEXPRESS; Integrated Security=true")
Dim sqlConn As SqlConnection
sqlConn = New SqlConnection("DataSource=..\..\Outcomes.sdf")
I am relatively new to sql, but know enough through tinkering to build a sql statement and get me the result I want. But I've never connected to a database before. I've looked on MSDN and tried several things I saw on there (everything that looked like what I needed, really) but it still hasn't worked.
If I can connect, I already have my statement set, and have tested it through the database itself. Any help would be wonderful, especially if it's explained in a way I can understand it and use it for later.
Also, if it helps and isn't noticed through my tried code, my db name is Outcomes. I don't know if that is needed or will help, but just in case.
Please visit connection strings here...
It also would have been helpful to know what type of DBMS you are using as well. I noticed you have an .sdf database file, not a DBMS (For ex: MySql, SQL or Oracle). Therefore, your connection string is really going to depend on what you want.
Your issue is here by the way...
Private sqlConn As New SqlConnection("Data Source=(local)|DataDirectory|\Outcomes.sdf;database=Outcomes;Integrated Security=true")
*You cant use the SqlConnection you have because its not supported with the use of .sdf files.
Instead you have to use: System.Data.SqlServerCe 'This is for compact edition
If you would like to know more about this please see here.
Kendra,
Here are the logical Steps you will need to follow to access the database programmatically:
Note: I'm assumming you have the proper SQLExpress | SQL Server Database setup whether local or remote the methods below are identical except for the connection string information.
1) Import the Sql AdoNet Namespace so you can use the proper SQL Server Client Objects & Methods;
a) Imports System.Data.SqlClient
2) Establish a Connection to the database with the ADO Connection Object:
' Create your ADO Connection Object:
Private myConn As SqlConnection
myConn = New SqlConnection("Initial Catalog=OutComes;" & _
"Data Source=localhost;Integrated Security=SSPI;")
Note: This connection string uses integrated security from your windows machine. you could also use standard security where you would need to enter your username and password credentials. Its your choice.
3) Setup Your ADO Command Object to Define your data retrieval query:
'Create a Command object.
Private myCmd As SqlCommand
myCmd = myConn.CreateCommand
myCmd.CommandText = "SELECT FirstName, LastName FROM Employees"
'Open the connection.
myConn.Open()
Note: Subsitute CommandText string for your actual query based upon your own database schema.
4) Read, Fetch, Display Data using the SQLDataReader Object:
Private results As String
Private myReader As SqlDataReader
myReader = myCmd.ExecuteReader()
'Traverse the DataSet and Display in GUi for Example:
Do While myReader.Read()
results = results & myReader.GetString(0) & vbTab & _
myReader.GetString(1) & vbLf
Loop
'Display results.
MsgBox(results)
5) Gracefully Close all Objects Used:
' Close the reader and the database connection.
myReader.Close()
myConn.Close()
Note - You'll need to consult microsoft for further connection string formats, since I don't have enough info. But this should clarify the actual big picture steps for you.
Regards,
Scott