Make SQLite connection fail if database is missing? (deleted/moved) - c#

I have the following method inside class DBConnection. I call the method like this: SQLiteConnection conn = DBConnection.OpenDB(); when I want to open an connection, so that I can execute my queries. I can call a similar method when I want to close the connection.
The method:
public static SQLiteConnection OpenDB()
{
try
{
//Gets connectionstring from app.config
string myConnectString =
ConfigurationManager.ConnectionStrings[
"LegMedSQLLite.Properties.Settings.LegMedSQLLiteDBConnectionString"].ConnectionString;
var conn = new SQLiteConnection(myConnectString);
conn.Open();
return conn;
}
catch (SQLiteException e)
{
MessageBox.Show(e.ToString(), "TEST");
return null;
}
}
This all works fine and dandy. The problem is the try-catch though. Let us imagine the following scenario:
The database file has been
moved/delete.
The exception will never be thrown. Actually, the first catch I stumble upon is when I execute my first query - where it figures that there is no such table(s) and it throws its own exception.
I was stunned by this weird phenomenon, but I soon found out that SQLite creates a new
empty database. By empty is mean no tables, nothing, just an SQLite database file with the same name as the old database which was supposed to be there.
This is an issue, I want the application to know if there is something wrong (database not found, corrupted, being used by another process etc.) as soon as I try to call SQLiteConnection conn = DBConnection.OpenDB();.
Naturally, I could try call a File.Exists in my method, but that doesn't seem like a proper solution. Any help?

If you're using System.Data.SQLite, you can add "FailIfMissing=True" to your connection string. SQLiteConnection.Open() will throw a SQLiteException if the database file does not exist.
string ConnectString = "Data Source=file.sdb; FailIfMissing=True";
DbConnection db = new SQLiteConnection(ConnectString);
db.Open(); // Fails if file.sdb does not exist
See SQLite Connection String Samples for another example, look for "Disable create database behaviour".
If you're using Microsoft.Data.Sqlite, you can specify an open mode with Mode=ReadWrite instead of Mode=ReadWriteCreate.

I haven't used SQLite but that is pretty bizarre behaviour to auto create a brand new database.
You could just adjust your try block to do a Select top 1 * From Table immediately after you open the connection, if it works, throw away the result and continue to return your conn object. If it fails, the exception handler should fire.

If you want to detect database corruption issues on start up , you can execute the command
pragma integrity_check;
or
pragma quick_check; ( which is faster, but less thorough )
This returns a single row with the value "ok".
Otherwise it will report errors that it encounters.

For sqlite use this: Suppose you have connection string in textbox txtConnSqlite
Using conn As New System.Data.SQLite.SQLiteConnection(txtConnSqlite.Text)
Dim FirstIndex As Int32 = txtConnSqlite.Text.IndexOf("Data Source=")
If FirstIndex = -1 Then MsgBox("ConnectionString is incorrect", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
Dim SecondIndex As Int32 = txtConnSqlite.Text.IndexOf("Version=")
If SecondIndex = -1 Then MsgBox("ConnectionString is incorrect", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
Dim FilePath As String = txtConnSqlite.Text.Substring(FirstIndex + 12, SecondIndex - FirstIndex - 13)
If Not IO.File.Exists(FilePath) Then MsgBox("Database file not found", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
Try
conn.Open()
Dim cmd As New System.Data.SQLite.SQLiteCommand("SELECT * FROM sqlite_master WHERE type='table';", conn)
Dim reader As System.Data.SQLite.SQLiteDataReader
cmd.ExecuteReader()
MsgBox("Success", MsgBoxStyle.Information, "Sqlite")
Catch ex As Exception
MsgBox("Connection fail", MsgBoxStyle.Exclamation, "Sqlite")
End Try
End Using
I think you can easilly convert it to c# code

This is specific to .NET Core.
Entity Framework Core 5.0 will throw this exception:
System.ArgumentException: Connection string keyword 'failifmissing' is not supported. For a possible alternative, see https://go.microsoft.com/fwlink/?linkid=2142181.
The alternative is to use Mode=ReadWrite in the Connection String.
string connectString = "Data Source=DbFileName.sdb; Mode=ReadWrite;";
ReadWriteCreate - Opens the database for reading and writing, and creates it if it doesn't exist. This is the default.
ReadWrite - Opens the database for reading and writing.
Refer the alternative link provided in the Exception message - https://go.microsoft.com/fwlink/?linkid=2142181
Types of Connection Mode - https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/connection-strings

Don't catch at that level. Instead, SQLiteConnection should implement IDisposable, meaning you should just return the open connection and allow calling code to handle any exceptions, as well as rely on the Dispose method to close the connection.

If there is no way to change the default SQLite behavior, then you might have to do a File.Exists. That would be better than connecting and creating a new file, checking to see if it's the database you want, then deleting the new file in the catch block.

Related

c# sqlite database locked when inserting

I am using SQLite in a C#
I have an insert query in a win form that works but on another win form that doesn't. when I have read about the issue it says it might be because there is an open connection somewhere but I have checked it all and even used SQLiteConnection.ClearAllPools(); after every close. now the 1st winform have only 1 open / close, the other one has 3.
I have tried the query using SQLite Browser to make sure it wasn't an issue with the query and it worked successfully. now when I debugged the issue occurs when this line executes cmd.ExecuteNonQuery(); that, of course, executes the query (insert into ....). so I tried changing the type of the table primary key (from varchar to integer). and I still have the issue. below is a sum of how it is.
myconnection = new SQLiteConnection(connectionString);
myconnection.Open();
//select stuff here
//verifications here
//insert inside verification
//finally { myconnection.close(); }
Did you try wrapping your connection in a using statement?
using(var myconnection = new SQLiteConnection(connectionString))
{
myconnection.Open();
//Your code here
}
This will call Dispose method of the connection regardless of execution path, which could possibly be doing more than just closing the connection.
Be aware to click on Write changes on SQLite browser,
if it is running and there are any unsaved changes!
In my case it was very stupid of me, I was making changes in the SQLite browser and did not click on write changes, which locked the DB to be modified by the services. After I clicked the Write changes button, all the post requests worked as expected.
According to #Rohan Shenoy in this topic: SQLite Database Locked exception
may be you should also try this
using (var con = new SQLiteConnection { ConnectionString = "connectionstring" })
{
using(var cmd = new SQLiteCommand { Connection = con })
{
// check state connection if open then close, else close proceed
if(con.State == ConnectionState.Open)
con.Close();
//then
try
{
// try connection to Open
con.Open();
}
catch
{
//catch if found error, message : 'Invalid Connection string'
}
........ // insert query here
} // Close Command
} // Close Connection

c# : one class to connect to sql server

Hello there I hope you're having a great time.
I have a question And I will break it down into 3 points:
1: create a class to connect to sql server the connection should be made using sql server authentication.
This class should contain several variables for connection parameters.
2: create a user form that shows the current connection parameters. And allow the user to update those parameters. In this form there should be a button to test the connect and another button to save the user changes to the connection parameters.
3: how to share the connection, created by the class we made in point 1, between different forms in the application. Without keeping too many open connections ideally only one connection should be open.
I will add the code that can solve this problem I hope that you can help me refine it.
I am new to all of this.
Thank you all for help.
already exists; SqlConnection and maybe SqlConnectionStringBuilder
that kinda already exists, via the IDE, but last time I checked this was not a redistributable dll. You could, however, simply hook a SqlConnectionStringBuilder to a PropertyGrid - or just write the UI from scratch
even "only one connection should be open" is wrong, IMO - let the inbuilt connection pooling deal with that; all you need is some configuration class with the connection string - and just deal with the connections as you need them, very locally - i.e.
using(var conn = new SqlConnection(Config.ConnectionString))
{
conn.Open();
// NOT SHOWN: do a couple of related operations
} // <== and here, it dies
1 : go to MSDN website you'll find what you need :
http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlcommand.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
2: look at your connection properties (http://msdn.microsoft.com/en-us/library/System.Data.SqlClient.SqlConnection_properties.aspx) and fill a listView or equivalent with it
3: Use previous SqlConnection.Open() to deal with it

Update table (rows) Access 2007 and C# 2010

So this is probably the most naive question but that is what questions are for I guess;
Then, my issue is that I have no idea on how to connect Visual C# Express 2010 to Access 2007 and do the typical insert, update, delete, search in an application in C#, I have just learned the basics (finished a console tutorial, which I believe is more than enought, having previous background of VB6 using access 97), and I have been searching here and in the web, but the only thing I could find where the msdn tutorials which I dind't find really clear.
So in my app I just need to link comboboxes, query those values to obtain new ones, do calculations and then store in arrays (and maybe show these in datagrids as well as edit them from said datagrids, which is a bit more complicated I guess) and finally store them in various tables, but I haven't really found a strong (or most likely simple) manual that will guide me to create the typical app insert, update, delete using winforms.
Do you guys have any good links in order to do this?
Thanks.
You can try with this code
Here link about string connection : http://www.connectionstrings.com/access-2007
var query = "...";
var connectionString = "...";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
// The insertSQL string contains a SQL statement that
// inserts a new row in the source table.
using(var command = new OleDbCommand(query))
{
// Set the Connection to the new OleDbConnection.
command.Connection = connection;
// Open the connection and execute the insert command.
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// The connection is automatically closed when the
// code exits the using block.
}
}

How to connect to an SQLite(CE) database on a windows mobile phone?

I want to make a database for my mobile 6 cellphone app. What I did was in visual studios I went to my project name and right clicked on it, went to add -> add new item -> data -> choose datafile.
It created a database file called "AppDatabase1.sdf"
Now I want to connect to my database but I don't know how what the connection string is since I see no app.config where I normally would expect it to be.
So I just have
SqlCeConnection conn = new SqlCeConnection("Not sure what to put here");
conn.Open();
When I click on the server explorer tab I see my database so I click on it. In the properties section it has something labeled "connection string" however it looks like the path to the actual file and when I run it in the emulator I get an error.
"The database file cannot be found.
Check the path to the database."
Thanks
You don't have to create the database outside your application. It is probably better if you had a fail-safe so that if the user accidentally deletes it or it does not exist, then you can re-create it easily. This is good for initial installations. The following code will do what you want (SQLCE/Mobile 2005 example):
Private Sub ConnectToDB()
If (File.Exists("\SystemCF\LPI\inventory.sdf")) Then
Try
cn = New SqlCeConnection("Data Source=\SystemCF\LPI\inventory.sdf;Password=")
cn.Open()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
ElseIf (File.Exists("\UserCF\LPI\inventory.sdf")) Then
Try
cn = New SqlCeConnection("Data Source=\UserCF\LPI\inventory.sdf;Password=")
cn.Open()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Else
Try
If (Not (Directory.Exists("\SystemCF\LPI"))) Then
Directory.CreateDirectory("\SystemCF\LPI")
End If
Dim engine As New SqlCeEngine("Data Source=\SystemCF\LPI\inventory.sdf")
engine.CreateDatabase()
cn = New SqlCeConnection("Data Source=\SystemCF\LPI\inventory.sdf")
cn.Open()
Call dropAndCreateDatabase()
Catch ex As Exception
MessageBox.Show(ex.Message)
MessageBox.Show("Unable to create database!", "Database Create Failed")
End Try
End Sub
SqlCeConnection connection = new SqlCeConnection();
connection.ConnectionString = "Data Source =" + filename + ";password=" + password;
connection.Open();
Of course, the password=<password> part is required only if you protected the DB, which is not the case by default.
BTW, this isn't SQLite, it's SQLServer CE (or SQLCE for short).
EDIT: If you only specify the file's name (no path), make sure that the file is in the current working directory. Obviously, according to the error message, there's something wrong with the way you specify the filename. My bet is on the path, just specify it and you should step forward.
EDIT2: In order to check if the problem is in your program or in the DB file, download DataPort Console and use it to open your DB in the device. That wayn you can validate that your DB can be accessed correctly.

How to fix "The ConnectionString property has not been initialized"

When I start my application I get: The ConnectionString property has not been initialized.
Web.config:
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=localhost\sqlexpress;Initial Catalog=mydatabase;User Id=myuser;Password=mypassword;" />
</connectionStrings>
The stack being:
System.Data.SqlClient.SqlConnection.PermissionDemand() +4876643
System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) +20
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +117
System.Data.SqlClient.SqlConnection.Open() +122
I'm fairly new to .NET and I don't get this one. I found a lot of answers on Google, but none really fixed my issue.
What does that mean? Is my web.config bad? Is my function bad? Is my SQL configuration not working correctly (I'm using sqlexpress)?
My main problem here is that I'm not sure where to start to debug this... anything would help.
EDIT:
Failling code:
MySQLHelper.ExecuteNonQuery(
ConfigurationManager.AppSettings["ConnectionString"],
CommandType.Text,
sqlQuery,
sqlParams);
sqlQuery is a query like "select * from table". sqlParams is not relevant here.
The other problem here is that my company uses MySQLHelper, and I have no visibility over it (only have a dll for a helper lib). It has been working fine in other projects, so I'm 99% that the error doesn't come from here.
I guess if there's no way of debuging it without seeing the code I'll have to wait to get in touch with the person who created this helper in order to get the code.
Referencing the connection string should be done as such:
MySQLHelper.ExecuteNonQuery(
ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString,
CommandType.Text,
sqlQuery,
sqlParams);
ConfigurationManager.AppSettings["ConnectionString"] would be looking in the AppSettings for something named ConnectionString, which it would not find. This is why your error message indicated the "ConnectionString" property has not been initialized, because it is looking for an initialized property of AppSettings named ConnectionString.
ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString instructs to look for the connection string named "MyDB".
Here is someone talking about using web.config connection strings
You get this error when a datasource attempts to bind to data but cannot because it cannot find the connection string. In my experience, this is not usually due to an error in the web.config (though I am not 100% sure of this).
If you are programmatically assigning a datasource (such as a SqlDataSource) or creating a query (i.e. using a SqlConnection/SqlCommand combination), make sure you assigned it a ConnectionString.
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings[nameOfString].ConnectionString);
If you are hooking up a databound element to a datasource (i.e. a GridView or ComboBox to a SqlDataSource), make sure the datasource is assigned to one of your connection strings.
Post your code (for the databound element and the web.config to be safe) and we can take a look at it.
EDIT: I think the problem is that you are trying to get the Connection String from the AppSettings area, and programmatically that is not where it exists. Try replacing that with ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString (if ConnectionString is the name of your connection string.)
The connection string is not in AppSettings.
What you're looking for is in:
System.Configuration.ConfigurationManager.ConnectionStrings["MyDB"]...
I stumbled in the same problem while working on a web api Asp Net Core project.
I followed the suggestion to change the reference in my code to:
ConfigurationManager.ConnectionStrings["NameOfTheConnectionString"].ConnectionString
but adding the reference to System.Configuration.dll caused the error "Reference not valid or not supported".
To fix the problem I had to download the package System.Configuration.ConfigurationManager using NuGet (Tools -> Nuget Package-> Manage Nuget packages for the solution)
I found that when I create Sqlconnection = new SqlConnection(),
I forgot to pass my connectionString variable. So that is why I changed the way I initialize my connectionString (and nothing changed).
And if you like me just don't forget to pass your string connection into SqlConnection parameters.
Sqlconnection = new SqlConnection("ConnString")
This what worked for me:
var oSQLConn = new
SqlConnection(
System.Configuration.ConfigurationManager.ConnectionStrings["Conn1"].ToString()
);
If you tried every answer mentioned above then there is the possibility that you are creating a new SQL connection based on the wrong sqlconnection check condition.
Below is the scenario :
The common method to return new SQL connection if it is not previously initialized else will return the existing connection
public SqlConnection GetSqlconnection()
{
try
{
if(sqlConnection!=null)
{
sqlConnection = new SqlConnection(WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
}
return sqlConnection;
}catch(Exception e )
{
WriteLog.WriteErrorLog(log, "GetSqlconnection() | ", e.Message, e.StackTrace);
throw e;
}
// return sqlConnection;
}
//here two methods which are using above GetSqlconnection() method
public void getUser()
{
//call to GetSqlconnection() method to fetch user from db
//connection.open()
//query execution logic will be here
//connection.close() <---here is object state changed --->
}
public void getProduct()
{
//call to GetSqlconnection() method with no connection string properties
//connection.open() ; <--- here exception will be thrown as onnectionstring-property-has-not-been-initialized
//query execution logic will be here .
//connection.close().
}
As soon as you close the connection in getUser() method there will two change in sqlconnection object
1.Status changed from 'Open' to 'Close'
2.ConnectionString property will be change to ""
hence when you call GetSqlconnection() method in getProduct() ,
accroding to if-Condition in GetSqlconnection() ,it will return the existing object of sqlConnection but with status as 'Closed' and ConnectionString as " ".
thus at connection.open() it will throw exception since connectionstring is blank.
To solve this problem while reusing sqlConnection we should check as below in GetSqlconnection() method :
try
{
if(sqlConnection==null || Convert.ToString(sqlConnection.State)=="Closed")
{
sqlConnection = new SqlConnection(WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
}
return sqlConnection;
}catch(Exception e )
{
WriteLog.WriteErrorLog(log, "GetSqlconnection() | ", e.Message, e.StackTrace);
throw e;
}
In my case, I missed a single letter in the word "ConnectionStrings" so it didn't match with the appsettings.json properties thus it gave me this error. An error could not be as deep as you may think. Start debugging by spelling mistakes.
I couldn't fix this exact problem nor have time to investigate, but in my case, it was related to Windows Server 2012 R2 or the framework version. The exact same code, app and config file worked flawlessly on other machines running other Windows versions. Tryed with at least the consumer versions (Windows 8, 10 and 11). Just Windows Server 2012 refused with the error in
System.Data.SqlClient.SqlConnection.PermissionDemand()
IN the startup.cs provide ConnectionStrings
for eg:
services.Configure<Readconfig>(Configuration.GetSection("ConnectionStrings"));
Use [] instead of () as below example.
SqlDataAdapter adapter = new SqlDataAdapter(sql, ConfigurationManager.ConnectionStrings["FADB_ConnectionString"].ConnectionString);
DataTable data = new DataTable();
DataSet ds = new DataSet();

Categories

Resources