sqlite in vb.net, can't find table even though it exists - vb.net

I'm using the following code (System.Data.SQLite within VB.net):
Dim SQLconnect As New SQLite.SQLiteConnection()
Dim SQLcommand As SQLiteCommand
SQLconnect.ConnectionString = "Data Source=vault.db;"
SQLconnect.Open()
SQLcommand = SQLconnect.CreateCommand
SQLcommand.CommandText = "INSERT INTO entries VALUES ('" & appinput.Text & "','" & userinput.Text & "','" & passinput.Text & "')"
SQLcommand.ExecuteNonQuery()
SQLcommand.Dispose()
SQLconnect.Close()
Me.Hide()
I get an error back that says it can't find the table "entries"
I know the table exists because I can write to it via the command line through sqlite and through Autoit and can see it and edit it in the SQLite browser when I open the database. I don't understand why VB can't see it (I know it sees and opens the database file just fine). Any ideas?

Most likely your problem is with relative paths (directories).
sqlite will create a database file if it does not exist so you will never get a "db file not found message". The first indication of an incorrect path is "table missing".
My personal experience is that although it goes against my programmers instinct is to alway use an absolute (fully qualified) path/file name for an sqlite database.
If you put in the full file location like "/var/myapp/vault.db" you should be OK.
If this is likly to move around store pick up the file name from a properties/config file -- 'config file not found' is much easier to deal with than "table not found".

Argh! There are 3 big issues in that code. Please update it like this to fix two of them:
Using cn As New SQLite.SQLiteConnection("Data Source=vault.db;"), _
cmd As New SQLiteCommand("INSERT INTO entries VALUES (#AppInput, #UserInput, #PassInput)", cn)
cmd.Parameters.AddWithValue("#AppInput", appinput.Text);
cmd.Parameters.AddWithValue("#UserInput", userinput.Text);
cmd.Parameters.AddWithValue("#PassInput", passinput.Text);
cn.Open()
cmd.ExecuteNonQuery()
End Using
This will prevent sql injection by parameterizing your query instead of substituting values directly and prevent db locking issues by making sure your connection is disposed properly, even if an exception is thrown.
The third problem is that you should NEVER store plain-text passwords in your database (or anywhere else for that matter). Go read up on how to hash values in .Net and hash and salt your password before storing or comparing it.
Once you've done that re-test your code to see if you still get the same errors reported as before. We need to make sure this didn't solve the problem or introduce something new. Then we can start addressing the missing table issue, perhaps by checking your connection string.

I had a similar error with SQLite (via .Net) refusing to believe the table existed, even though direct access confirmed it was there. The error could be produced only on one individual machine and not others. Hard coding the path didn't seem to fix the problem. The fix was either to run the program as Administrator or change the DB file to be available to Everyone. Apparently the .Net assembly raises a missing table error when the actual problem is access restrictions.

Related

Getting an E_OUTOFMEMORY when accessing an Access database with OLEDB

We have this VB.net code that connects to an MS Access Database and tries to insert a new entry:
Dim conn As New OleDbConnection
conn.ConnectionString = "Provider="Microsoft.ACE.OLEDB.16.0; Data Source=" & DATABASE_PATH & ";Jet OLEDB:Database Password=pass;"
conn.Open()
Dim SqlString As String = "INSERT INTO tblNotes" &
" ([NotesNumber" &
"], [NotesTitle" &
"], [HasAdditionalLogic" &
"], [TypeId]) Values (?,?,?,?)"
Dim cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("NotesNumber", 1234)
cmd.Parameters.AddWithValue("NotesTitle", "the title")
cmd.Parameters.AddWithValue("HasAdditionalLogic", False)
cmd.Parameters.AddWithValue("TypeId", 14)
cmd.ExecuteNonQuery()
conn.close()
Nothing too fancy, right?
This code worked fine with Access 2016 installed.
Now with the recent upgrade to Office 365 the line
cmd.ExecuteNonQuery()
causes this error:
'Microsoft.ACE.OLEDB.16.0' failed with no error message available, result code: E_OUTOFMEMORY(0x8007000E)
Googling for that error message lead to several ideas like using Integer instead of Long Integer in the database, but that did not help either.
And personally, I doubt that the root cause is a lack of memory because the machine has 32GB RAM installed and is set to 32GB of Virtual Memory. The process itself never uses more than 100MB, Windows Process Explorer tells us that the whole RAM uses about 5GB total. So I just cannot believe we are actually running out of memory here.
Any idea?
Update:
Okay, we seem to have found the underlying issue here.
You see this line:
cmd.Parameters.AddWithValue("TypeId", 14)
In the Access database, the field "TypeId" has been defined as a Primary Key of Data Type "AutoNumber" and Field Size "Long Integer".
Now, if we write the code like this:
cmd.Parameters.AddWithValue("TypeId", 14I)
it runs without an error, but as soon as we change it to:
cmd.Parameters.AddWithValue("TypeId", 14L)
we get the crash.
Let me state again that the code with a Long works fine with Access 2016, it crashes with the Access from Office 365.
I may be mistaken, but this seems like a bug in Access.
Of course we can now change all the app code from Long to Integer (or UInteger), but this seems like treating the symptoms instead of the root cause.
Can somebody confirm this? Or tell me why exactly this happens? Using a Long seems to be correct to me, using an Integer instead seems pretty wrong to me.
To anybody who might face the same problem: we "fixed" the issue by installing "Microsoft Access Database Engine 2010 Redistributable"
https://www.microsoft.com/en-US/download/details.aspx?id=13255
and then using
Microsoft.ACE.OLEDB.12.0
instead of
Microsoft.ACE.OLEDB.16.0
That did the trick.
The hint with .add instead of .addWithValue did not make any difference.

Importing a text file into Postgres using ODBC

I am trying to directly import a text file into Postgres, but using ODBC. I realize that this is a bit of an odd thing to do, but ODBC does a good job of fixing/ignoring errors in the text files and Postgres' Copy command is very, very picky. I use Copy when I can and ODBC where I can't.
I am currently doing this in two steps. ODBC Import to Access and then from Access to Postgres but I recently learned over on MSDN I may be able to do this in one step but am having trouble with the SQL.
Here is the code I am using:
Dim TextConnection As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\PathToTextFile;Extended Properties=""Text;HDR=No""")
Dim TextCommand As System.Data.OleDb.OleDbCommand
TextCommand = New System.Data.OleDb.OleDbCommand("SELECT * INTO [ODBC;Driver={PostgreSQL};" & _
" Server=server;Database=database;Uid=UserName;Pwd=Password;].[TableName] FROM [textfile.txt]", TextConnection)
TextCommand.ExecuteNonQuery()
I am getting this error: Query input must contain at least one table or query.
I am not where to go from here in debugging this. It also just might now be possible and that would be good to know.

Errors With SQLite and VB.net when reading database

I seem to be receiving random error messages when trying to read queries from a SQLite DB stored on a network drive. On my development machine, I rarely ever get an error, but users are reporting random errors such as:
Unable to open database. File is encrypted or is not a database
Database disk image is malformed
Or it just doesn't return any data.
My code looks like such:
Private Sub LoadStoreCalls()
Dim tmpID As String
Dim QryString As String
Dim SQLconnect As New SQLite.SQLiteConnection()
SQLconnect.ConnectionString = "Data Source=" & SpiceWorksPath & ";New=False;Compress=True;Read Only=True;"
Try
'Open a connection to the database
SQLconnect.Open()
'Get StoreCode
tmpID = Mid(StoreCode, 2) & "-" & StoreName
QryString = "SELECT id, summary, status, c_location, c_store_device FROM tickets WHERE status = 'open' AND c_location = '" & tmpID & "'"
Dim ExQry As New SQLiteCommand(QryString, SQLconnect)
ExQry.CommandType = CommandType.Text
Dim da As New SQLiteDataAdapter(ExQry)
dasSpice.Clear()
da.Fill(dasSpice, "Calls")
SQLconnect.Close()
Catch ex As Exception
If SQLconnect.State = ConnectionState.Open Then SQLconnect.Close()
MsgBox(ex.Message)
End Try
End Sub
The problem is that my application relies on this data being returned to populate additional entries of a datagridview control, and because I cannot replicate this error on my development machine using debug, I cannot find where the fault is occurring.
If the user gets one of these errors, they usually keep trying to run the query and eventually it will work. Or they just exit my application and go back in and then it seems to work for a while. The errors are random and not always from running the same query.
I'm assuming it's due to an issue talking to an SQLite DB on a shared drive, but I can't find any information regarding setting timeouts. I also can't work out how to 'catch' the error because I can't replicate it myself. I have tried adding logging details to the Catch event handler, but it simply just returns me the error message (above) in the logs.
Any help would be greatly appreciated.
Thanks
After many hours of troubleshooting and researching I found that SQLite does not play well with remote connections. Not only was it causing errors in my application, it was also throwing errors in the parent application.
My alternative was to write an application to query the database that ran locally on the SQLite machine. This fixed all of my issues.
For anyone interested...

Nested With Statement Crashes

After Visual Studio 2010 locked up earlier today, a code segment that contains a nested With statement no longer works, and locks up, and I have to use Task Manager to terminate VS-2010.
I had a block of code as follows:
With cmd ' OleDbCommand object
With .Parameters '<------- locks up when executing this line
.AddWithValue("#Parm1", Parm1Value)
.AddWithValue("#Parm2", Parm2Value)
' Etc.
End With
.ExecuteNonQuery()
End With
This ran fine, until VS locked up earlier. I had to delete the SUO files from the directory so that VS would not complain when trying to open the documents I had opened previously. But then this nested With-statement stopped working.
However, the following two variations of the code work fine:
With cmd
With cmd.Parameters '<--- with cmd explicitly specified
.AddWithValue("#Parm1", Parm1Value)
.AddWithValue("#Parm2", Parm2Value)
' Etc.
End With
.ExecuteNonQuery()
End With
and
cmd.Parameters.AddWithValue("#Parm1", Parm1Value)
cmd.Parameters.AddWithValue("#Parm2", Parm2Value)
cmd.ExecuteNonQuery()
Any nested With statement that leverages the outer With statement fails the same way (i.e. does not have to be in conjunction with OleDb objects) I did a small test project that did a With on the form object, and a nested With on a sub-object ... same results: it locked up.
I ran the VS-2010 installation to do a repair, and it still behaves this way. Rebooting also does not fix the problem.
I can just code that a different way, but I shouldn't have to, and secondly, who knows what else got messed up when VS crashed that first time?!!
I was hoping to not have to do a full uninstall/reinstall of VS-2010.
Has anyone else seen this problem?
Were you working on this solution/project when VS2010 crashed?
Were you confronted with a project file recovery option before and/or after you removed the SUO file?
As a point of interest, test initializing Anonymous objects using the with statement:
Dim cust0 = New With {.Name = "Toni Poe", .City = "Louisville"}
Have your tried a 'Clean' & 'Rebuild' on your solution.
Try creating a new solution/project and testing a nested with statement on a new OleDbCommand object.
Though, you'll probably feel better with a clean install of VS2010. I suspect your solution is corrupt, not vs2010.

Problem reading dBase DBF with non-English characters

I have a tool which reads dBase files and uploads the contents to SQL Server, part of a system to import shapefiles. It works but now we have a requirement to import files that include non-English characters (Norwegian in this case, could be other languages later) and they're being corrupted.
The dBase files are being read using an OleDbDataAdapter. Stepping through the code I can see that the text is wrong as it is read in. I'm assuming it's something to do with code pages or Unicode but I have no idea how to fix it.
A dBase Reader application tells me the DBFs are in code page 1252 - I don't know if this is correct. My upload tool runs on Win7 with English (UK) regional settings.
Examples:
ÅSGARD in DBF becomes +SGARD in VB.Net & SQL Server.
RINGHORNE ØST in DBF becomes RINGHORNE ÏST in VB.Net & SQL Server.
The code that reads the DBF:
dbfConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath & ";Extended Properties=dBASE IV"
Cnn.ConnectionString = dbfConnectionString
Cnn.Open()
strSQL = "SELECT * FROM [" & strDBF & "]"
DA = New OleDb.OleDbDataAdapter(strSQL, Cnn)
DS = New DataSet
DA.Fill(DS)
If DS.Tables(0).Rows.Count > 0 Then
dtDBF = DS.Tables(0)
Else
dtDBF = Nothing
End If
Data is read like: Name = dtDBF.Rows(index)("NAME_1")
Is there a way to tell OleDbDataAdapter what code page to use or a better way to read dBase files from VB.Net?
Try adding this to your DSN:
CollatingSequence=Norwegian-Danish
You might also be able to use:
CollatingSequence=International
Check whether the shapefile contains codepage information. There are two places to look
Look in the language driver ID (LDID), which is found in the header of the shapefile’s DBF table (in the 29th byte).
Look for an associated separate file with extension .cpg.
If the code page is not specified in those locations, it defaults to the codepage on the PC that generated the shapefile. You will just have to know that :(
I've never used it, but maybe Shape2SQL takes care of this for you? Or shp2text? I believe the PostGIS shapefile loader handles code pages: maybe you could import into PostGIS and then export in another format??
Old question, but this may answer it for future readers...
You might try adding a property setting in your connection string:
Locale Identifier=1044
This property (and a list of values including this one) is documented for ADO in conjunction with Jet 4.0's OLDB Provider but I have no reason to believe it isn't also supported by ADO.Net. This value (1044) is Norwegian/Danish.
Untested, but something else to try.