SQLite database file can't be opened when placed in network folder - vb.net

Can someone help me to understand why this works fine...
Dim cs = "Data Source=C:\folder\Livros.sdb;Version=3;"
Dim cn = New System.Data.SQLite.SQLiteConnection(cs)
cn.Open() ' no exception
... while this breaks when opening connection (it is exactly the same file)...
Dim cs = "Data Source=\\NetworkServer\folder\Livros.sdb;Version=3;"
Dim cn = New System.Data.SQLite.SQLiteConnection(cs)
cn.Open() ' exception: {"unable to open database file"}
... and fix it because I need to place database file in network location so I can access it regardless of the computer I run the application?
Thank you very much!

Ok, so by trial and error I found the solution, although I can't quite understand the reason it works:
Dim cs = "Data Source=\\NetworkServer\folder\Livros.sdb;Version=3;"
Dim cn = New System.Data.SQLite.SQLiteConnection(cs)
cn.ParseViaFramework = True ' JUST ADDED THIS STATEMENT
cn.Open() ' no exception
If somebody can explain why .ParseViaFramework = True does the trick, please feel free to comment.

Similar question was asked here.
SQLite: Cannot open network file programmatically, even though worked before
The top answer gives a few more fixes. Linking here as this is the first stackoverflow that came up when I searched. Also I was using a SQLiteConnectionStringBuilder and could not find a way to set the parseViaFramework so the first solution was the one I needed.
Double the leading two backslashes in the file name (e.g. "\\\\network\share\file.db").
Use a mapped drive letter.
Use the SQLiteConnection constructor that takes the parseViaFramework boolean argument and pass 'true' for that argument.

Related

Additional information: There is already an open DataReader associated with this Command which must be closed first. vb.net

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.

Why GetFiles from a remote folder using Linq is hanging

I'm trying to fetch the files inside a folder ordered by LastWriteTime.
The code is running very fast when accessing to a local path (C:\MyFolder), but is hanging when accessing to a remote path (\\MyServer\MyFolder)
Dim myOrderedList As List(Of String) = (From item In IO.Directory.GetFiles(strFolderSource) _
Let file = New IO.FileInfo(item) _
Order By file.LastWriteTime _
Select item).ToList()
Should this code work? Is not allowed this method to get files from a remote folder?
Which alternative code could I use to get the same result without hanging?
EDITED (2019-01-18 16:32):
Sorry guys, I've tried the proposed solution from Rango, and still the same hang. Finally I created a small logging system to catch the step that caused the problem, and realized that all is a credential problem.
Just before the code I posted I do a NET USE to grant access to the remote computer, and the net use is executed, but for any reason, the GetFiles() fails because of Logon failure: unknown user name or bad password.
So, Could I ensure the credentials with the net use before call the GetFiles()?
Maybe using a pause or something like this?
FULL CODE:
Dim processInfo As New System.Diagnostics.ProcessStartInfo()
processInfo.FileName = "C:\WINDOWS\system32\net"
processInfo.Arguments = "net use \\MyServer\IPC$ ""password"" /USER:Username"
System.Diagnostics.Process.Start(processInfo)
Dim myOrderedList As List(Of String) = (From item In IO.Directory.GetFiles("\\MyServer\g$\MyFolder") _
Let file = New IO.FileInfo(item) _
Order By file.LastWriteTime _
Select item).ToList()
You could try to use DirectoryInfo.EnumerateFiles instead wich has two advantages:
No consecutive security handshakes from the remote server necessary
Streaming the files instead of loading all into memory before you start ordering them
Dim di = new DirectoryInfo(strFolderSource)
Dim files = From fi In di.EnumerateFiles() Order By fi.LastWriteTime Select fi.FullName
Dim myOrderedList As List(Of String) = files.ToList()
Finally solved including a sleep of 5 seconds after the net use and before the GetFiles():
System.Threading.Thread.Sleep(5000)
Thanks for your time, and hope this helps anybody with a similar problem.

Setting MS Access password at runtime in vb.net designer generated system

I am developing a VB.NET update system for a volunteer organisation’s MS Access database. The database is protected by a password as it contains personal information. I have created the application using the VB designer. I need to be able to code the application so that, if the owner decides to change the MS Access password, they will have no need to come back to me to change the code and rebuild the solution. In other words, I do not want the password to be hard coded in the app.config file or the settings.designer.vb file. My code should not need to know the password as a simple call to one of the Fill functions can test any password entered by the user. My problem is that I have found no way to alter the connection string that is tested in the setttings.designer.vb code whenever the database is accessed. I am using Visual Studio 2017.
I have spent a long time searching the web for answers and have tried various solutions involving the configurationmanager without success. I am new to this area so I would be most grateful if anyone here can help.
Here is my latest attempt which still produces an invalid password error even though the third debug statement suggests that the connection string, including the password, has been correctly set.
Public Sub UpdateConnString(connString As String)
Dim configFileMap As New ExeConfigurationFileMap()
Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(configFileMap.ExeConfigFilename)
Dim connStringName As String = "TestConnectionString"
Debug.Print("0 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString = connString
Debug.Print("1 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
config.Save(ConfigurationSaveMode.Modified, True)
Debug.Print("2 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
End Sub
Just because a connection string is stored in the config file, you aren't required to use it as it is. You can read in that default value and then edit it before using it, e.g.
Dim builder As New OleDbConnectionStringBuilder(My.Settings.DefaultConnectionString)
builder.DataSource = dataSource
Dim connectionString = builder.ConnectionString
You can add or modify any part of a connection string you want that way at run time.
Thank you for your response. Unfortunately, the code throws a compilation error - "DefaultConnectionString is not a member of My.Settings".
Fortunatley I have now managed to find a working solution:
'My.Settings.Item("TestConnectionString") = connectionString

SAS VBA connection

I tried to run a SAS code through VBA. I'm running SAS on a server. I have a test SAS program "Program1.sas" which I've kept on the server. Below is the VBA code that I've used. The SAS code is running but the output dataset is just showing the column headers and the rows are empty.Can anyone help me what could be the possible reason.
Sub Form_Load23()
Dim obObjectFactory As New SASObjectManager.ObjectFactory
Dim obObjectKeeper As New SASObjectManager.ObjectKeeper
Dim obServer As New SASObjectManager.ServerDef
Dim obSAS As SAS.Workspace
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
obServer.MachineDNSName = "xyz"
obServer.Protocol = SASObjectManager.Protocols.ProtocolBridge
obServer.Port = 8871
obObjectFactory.LogEnabled = True
Set obSAS = obObjectFactory.CreateObjectByServer("sas", True, obServer,"userid", "password")
obSAS.LanguageService.Submit ("options source2; %include '/abc/AFP/shikhar.gupta1/amg/**Program1.sas**';")
End Sub'
I believe you have to change the security settings in excel. Find the security settings and protected viewing. The remove all the check marks.
This is an issue on the SAS side. It can happen when your user does not have the metadata 'read' permission on the relevant dataset. It can also happen if your program has an error, and options obs=0; is set.
As #vasilij mentions, use proc printto to write your log to a file system and check for issues, also use SMC to check your metadata permissions.

VB.net Getting Scalar to save a value to a variable

I've been looking through the forums with no luck. I am trying to retrieve a value from a database and store it to a variable. The closest I got was following This. Here is my Code:
Dim dblAircraftHourlyRate As Double
Dim intAircraftID As Integer
intAircraftID = ddAircraft.SelectedItem.Value
Dim mySqlComm As String = "SELECT HourlyRate FROM Aircraft WHERE AircraftID = '" & intAircraftID & "'"
Using cn As New SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Rollin Laptop\Desktop\CurrentAll2Fly3\App_Data\ASPNETDB.MDF;Integrated Security=True;User Instance=True"), _
cmd As New SqlCommand(mySqlComm, cn)
cn.Open()
dblAircraftHourlyRate = Convert.ToDouble(cmd.ExecuteScalar())
End Using
I'm not sure why, but instead of saving the HourlyRate to the dblAircraftHourlyRate, it is saving the intAircraftID to dblAircraftHourlyRate. I'm also not sure why the example code did not close the database connection. Any ideas on how to fix this to get the correct variable?
My solution had nothing to do with the question, but I had a separate bit of code that was executing after the bit I posted. It was resetting the value of dblAircraftHourlyRate such that dblAircraftHourlyRate = ddAircraft.SelectedItem.Value After I commented out the line, the code worked perfectly. To clarify, the value in the dropdownlist was the AircraftID, not the HourlyRate.
Tim Schmelter also helped me out in his explanation of how Connection-Pooling works:
Connection-Pooling is enabled by default. Default means that it's enabled even if you don't specify the Pooling parameter in your connection-string. Connection-pooling helps to improve performance since it maintains the state of the physical connections. So even if you close a connection the physical connection keeps open (If you check it in the database). You are using the Using-statement which is best practise. Disposing a connection will "close" it. – Tim Schmelter