I have a webservice running on IIS, which contains the class to connect to the SQL server. Most of the time, we are able to connect the SQL server using the below code. But some time we could not connect the sql server. We are not getting any error. Here is the source code:
public SqlConnection DbConnectSql()
{
string str = "Server=xxxx\xxx;database=production;Timeout=60000;user id=sa;password=888*;";
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
We are not getting any response during the execution of _con.Open();. We could not understand why we are not getting any response. I have to restart the IIS every 2 days to open the SQL connection. Can anyone let me know the why I have to restart the IIS to work _con.Open(); method?
Here's an interleaving of two calls to DbConnectSql that will a) end up with two threads sharing use of one connection object and b) leaks an open connection object:
//Thread 1
public SqlConnection DbConnectSql()
{
string str = ...;
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
//Thread 2
public SqlConnection DbConnectSql()
{
string str = ...;
//-->Look, thread 2 is overwriting _con-->
_con = new SqlConnection(str);
return _con;
}
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
If we're lucky, then the first caller won't try to use the connection object before the second caller gets around to calling Open on it1. But the connection created by the first caller has been opened and now nobody has a reference to it.
You'll be getting errors because the connection pool (eventually) becomes exhausted and so the Open call will throw an exception. Why you don't see the exception isn't diagnosable from the code shown.
You're probably being lucky to last 2 days at a time, because these connections are eligible for garbage collection and so will eventually be returned to the connection pool.
Far better to just share the connection string around. Construct SqlConnection (and SqlCommand) objects in using statements that keep them nicely locally scoped and ensures that they are cleaned up neatly. You don't need this DbConnectSql function. It's doing more harm than good.
1And there are likely to be other possible errors here, if one caller tries to retrieve a result set whilst the other caller is still retrieving one.
I am creating a console application and keep the SQL operations in a separate class file. When I execute the application it raises an exception:
ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
However, in SQL class file's constructor I wrote the code for SqlConnection.Open().
Code for Main application:
using SQL;
class MyClass
{
SQL.executeSQL runSQL=new SQL.executeSQL();
static void Main(string[] args)
{
CheckCounts();
}
public void CheckCounts()
{
string sql="select count(*) from table_name";
runSQL.executeQuery(sql);
}
}
Code for SQL class file:
public class executeSQL
{
SqlConnection con=new SqlConnection(ConfigurationManager.ConnectionString["dbConnection"].ToString());
public executeSQL()
{
if(con.State!=ConnectionState.Open)
{
con.Open();
}
}
public void executeQuery(string sql)
{
SqlCommand cmd=new SqlCommand(sql,con);
cmd.ExecuteNonQuery();
}
}
When I execute the application for the first time for that day it raises the exceptions as follows
ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
But for next time it runs properly without any exception for the whole day.
Again if I run the application for the next day it raises the same exception and consecutive successful execution.
What should I do to run the application successfully for the first time of the day?
I created a batch file for the application and I scheduled the task using the Task Scheduler with the batch file. If I run the application manually I do not get the error. Using the Task Scheduler, I am getting the error.
This can happen for a few reasons.
Chances are, you're connecting to a remote SQL server.
If this is the case, then there are a variety of reasons why the connection may be closed on you by the time you make your call.
Things like network dropouts etc can cause the connection between your app and SQL to break and require reconnection.
It can also be caused by the agreed timeout between your app and SQL being exceed, however I doubt this is the case given your code sample.
I have personally experienced issues where I have made what appears to be a valid connection to the server, and then on the very next line attempt to make a SQL query, only to receive the same error as yourself.
In those instances, I've added a check before making my SQL query around the SQLConnection.State property, which can return any of the following:
Broken
The connection to the data source is broken. This can occur only after
the connection has been opened. A connection in this state may be
closed and then re-opened. (This value is reserved for future versions
of the product.)
Closed
The connection is closed.
Connecting
The connection object is connecting to the data source.
Executing
The connection object is executing a command. (This value is reserved
for future versions of the product.)
Fetching
The connection object is retrieving data. (This value is reserved for
future versions of the product.)
Open
The connection is open.
If the SqlConnection.State is Open, then I run my SQL query as intended.
If it's Closed, I attempt to re-open it then re-call my SQL query.
If it's Connecting, I pause for a specific amount of time, then retest.
Depending on how you want your app to perform, I would look at either moving the creation of the SQLConnection into the method that makes the SQL call, as follows:
public class executeSQL
{
private void CheckSQLConnection(SqlConnection con)
{
...
}
public void executeQuery(string sql)
{
using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ToString()))
{
con.Open();
using (var cmd = new SqlCommand(sql, con))
{
CheckSQLConnection();
cmd.ExecuteNonQuery();
}
con.Close();
}
}
}
As in my example, it's also worth implementing using statements around your SQLConnection and SQLCommand objects to ensure they're properly disposed of and don't hang around, potentially holding onto SQL connections you might need.
Hope this helps!
My application makes one query to a SQLite database every 3 seconds, but after about 20 minutes, at the time of executing the command, it throws the exception "Attempt to write a readonly database". I just need to read the database.
Imports:
using System.Data.Sqlite;
This is my connection string:
sqlite_conn = new SQLiteConnection("Data Source=Patch_here;Version=3;Compress=True;Read Only=True"
This is the method where throws the excepcion. This Method is executed every 3 seconds:
Double fecha = 0;
try
{
sqlite_cmd = new SQLiteCommand(sqlite_conn);
sqlite_cmd.CommandText = "SELECT MAX(timestamp) FROM Messages";
//HERE throws the exception, when executes the command.
fecha = Double.Parse(sqlite_cmd.ExecuteScalar().ToString());
sqlite_cmd.Dispose();
}
catch (Exception ex)
{
informarError(ex.Message);
}
return timestamp_To_Datetime(fecha);
Additionally,
- My user has all privileges for this database.
- My SQLiteConnection just is opened one time for all queries.
What can I do? Thanks.
(I know, this is rather old. Maybe this is help for another person..)
I had a similar problem:
Database is under (write) load (is filled with an C/C++ program). At the same time a C# program send periodically a select count(*). Sometimes (very rare) it except with the error mentioned.
I "solved" this by removing "Read Only=True" from the connect string.
I know this is one of the most popular questions on SO: The Famous "SQL error 26" the difference is that my C# application establishes a connection successfully the first time and then refuses to establish a connection the second time. I restart my computer and the application establishes a connection the first time and then requires a restart again.
The fact that I can establish a connection the first time makes me feel confident that: My server name is correct, My instance name is correct, the username and password combination I use are correct, the server machine is on, the SQL Browser service on the server is running, and I can get through the firewall.
I have a bunch of methods that all look very similar to the following:
private static string connection_string = #"Server=my_server\MS_SQL;User Id=user1;Password=password1"
public static List<string> GetListOfExistingItems(int item_id)
{
List<string> list_items = new List<string>();
try
{
using (SqlConnection sql_conn = new SqlConnection(connection_string))
{
sql_conn.Open();
SqlCommand sql_comm = new SqlCommand("SELECT Name FROM dbo.table1 WHERE ID=" + item_id,
sql_conn);
using (SqlDataReader sql_reader = sql_comm.ExecuteReader())
{
while (sql_reader.Read())
{
list_items.Add(sql_reader["Name"].ToString());
}
sql_reader.Close();
}
}
}
catch (Exception excp)
{
throw new Exception(excp.Message);
}
return list_items;
}
A few interesting facts:
A restart fixes the problem (once).
A log out and log in does NOT fix the problem.
If I do not close the application but instead run the query multiple times, the error does not show up.
I cannot connect to my database from SQL Server Management Studio after I run my application and close it once.
When I restart my computer I see the "Waiting for background programs to close" without any programs being listed. I wait for some time (maybe 10-20 seconds) and the message goes away and the computer eventually restarts.
Thanks in advance.
Somewhere you're not closing your connection.
My next troubleshooting step would be to string-search your code (all of it) for sql_conn.Open();, and find the one(s) not in a using block, or otherwise not getting explicitly closed.
I'm performing a large number of INSERTS to a SQLite database. I'm using just one thread. I batch the writes to improve performance and have a bit of security in case of a crash. Basically I cache up a bunch of data in memory and then when I deem appropriate, I loop over all of that data and perform the INSERTS. The code for this is shown below:
public void Commit()
{
using (SQLiteConnection conn = new SQLiteConnection(this.connString))
{
conn.Open();
using (SQLiteTransaction trans = conn.BeginTransaction())
{
using (SQLiteCommand command = conn.CreateCommand())
{
command.CommandText = "INSERT OR IGNORE INTO [MY_TABLE] (col1, col2) VALUES (?,?)";
command.Parameters.Add(this.col1Param);
command.Parameters.Add(this.col2Param);
foreach (Data o in this.dataTemp)
{
this.col1Param.Value = o.Col1Prop;
this. col2Param.Value = o.Col2Prop;
command.ExecuteNonQuery();
}
}
this.TryHandleCommit(trans);
}
conn.Close();
}
}
I now employ the following gimmick to get the thing to eventually work:
private void TryHandleCommit(SQLiteTransaction trans)
{
try
{
trans.Commit();
}
catch (Exception e)
{
Console.WriteLine("Trying again...");
this.TryHandleCommit(trans);
}
}
I create my DB like so:
public DataBase(String path)
{
//build connection string
SQLiteConnectionStringBuilder connString = new SQLiteConnectionStringBuilder();
connString.DataSource = path;
connString.Version = 3;
connString.DefaultTimeout = 5;
connString.JournalMode = SQLiteJournalModeEnum.Persist;
connString.UseUTF16Encoding = true;
using (connection = new SQLiteConnection(connString.ToString()))
{
//check for existence of db
FileInfo f = new FileInfo(path);
if (!f.Exists) //build new blank db
{
SQLiteConnection.CreateFile(path);
connection.Open();
using (SQLiteTransaction trans = connection.BeginTransaction())
{
using (SQLiteCommand command = connection.CreateCommand())
{
command.CommandText = DataBase.CREATE_MATCHES;
command.ExecuteNonQuery();
command.CommandText = DataBase.CREATE_STRING_DATA;
command.ExecuteNonQuery();
//TODO add logging
}
trans.Commit();
}
connection.Close();
}
}
}
I then export the connection string and use it to obtain new connections in different parts of the program.
At seemingly random intervals, though at far too great a rate to ignore or otherwise workaround this problem, I get unhandled SQLiteException: Database file is locked. This occurs when I attempt to commit the transaction. No errors seem to occur prior to then. This does not always happen. Sometimes the whole thing runs without a hitch.
No reads are being performed on these files before the commits finish.
I have the very latest SQLite binary.
I'm compiling for .NET 2.0.
I'm using VS 2008.
The db is a local file.
All of this activity is encapsulated within one thread / process.
Virus protection is off (though I think that was only relevant if you were connecting over a network?).
As per Scotsman's post I have implemented the following changes:
Journal Mode set to Persist
DB files stored in C:\Docs + Settings\ApplicationData via System.Windows.Forms.Application.AppData windows call
No inner exception
Witnessed on two distinct machines (albeit very similar hardware and software)
Have been running Process Monitor - no extraneous processes are attaching themselves to the DB files - the problem is definitely in my code...
Does anyone have any idea whats going on here?
I know I just dropped a whole mess of code, but I've been trying to figure this out for way too long. My thanks to anyone who makes it to the end of this question!
brian
UPDATES:
Thanks for the suggestions so far! I've implemented many of the suggested changes. I feel that we are getting closer to the answer...however...
The code above technically works however it is non-deterministic! It is not guaranteed to do anything aside from spin in neutral forever. In practice it seems to work somewhere between the 1st and 10th iteration. If i batch my commits at a reasonable interval damage will be mitigated but I really do not want to leave things in this state...
More suggestions welcome!
It looks like you failed to link the command with the transaction you've created.
Instead of:
using (SQLiteCommand command = conn.CreateCommand())
You should use:
using (SQLiteCommand command = new SQLiteCommand("<INSERT statement here>", conn, trans))
Or you can set its Transaction property after its construction.
While we are at it - your handling of failures is incorrect:
The command's ExecuteNonQuery method can also fail and you are not really protected. You should change the code to something like:
public void Commit()
{
using (SQLiteConnection conn = new SQLiteConnection(this.connString))
{
conn.Open();
SQLiteTransaction trans = conn.BeginTransaction();
try
{
using (SQLiteCommand command = conn.CreateCommand())
{
command.Transaction = trans; // Now the command is linked to the transaction and don't try to create a new one (which is probably why your database gets locked)
command.CommandText = "INSERT OR IGNORE INTO [MY_TABLE] (col1, col2) VALUES (?,?)";
command.Parameters.Add(this.col1Param);
command.Parameters.Add(this.col2Param);
foreach (Data o in this.dataTemp)
{
this.col1Param.Value = o.Col1Prop;
this. col2Param.Value = o.Col2Prop;
command.ExecuteNonQuery();
}
}
trans.Commit();
}
catch (SQLiteException ex)
{
// You need to rollback in case something wrong happened in command.ExecuteNonQuery() ...
trans.Rollback();
throw;
}
}
}
Another thing is that you don't need to cache anything in memory. You can depend on SQLite journaling mechanism for storing incomplete transaction state.
Run Sysinternals Process Monitor and filter on filename while running your program to rule out if any other process does anything to it and to see what exacly your program is doing to the file. Long shot, but might give a clue.
We had a very similar problem using nested Transactions with the TransactionScope class. We thought all database actions occurred on the same thread...however we were caught out by the Transaction mechanism...more specifically the Ambient transaction.
Basically there was a transaction higher up the chain which, by the magic of ado, the connection automatically enlisted in. The result was that, even though we thought we were writing to the database on a single thread, the write didn't really happen until the topmost transaction was committed. At this 'indeterminate' point the database was written to causing it to be locked outside of our control.
The solution was to ensure that the sqlite database did not directly take part in the ambient transaction by ensuring we used something like:
using(TransactionScope scope = new TransactionScope(TransactionScopeOptions.RequiresNew))
{
...
scope.Complete()
}
Things to watch for:
don't use connections across multiple threads/processes.
I've seen it happen when a virus scanner would detect changes to the file and try to scan it. It would lock the file for a short interval and cause havoc.
I started facing this same problem today: I'm studying asp.net mvc, building my first application completely from scratch. Sometimes, when I'd write to the database, I'd get the same exception, saying the database file was locked.
I found it really strange, since I was completely sure that there was just one connection open at that time (based on process explorer's listing of active file handles).
I've also built the whole data access layer from scratch, using System.Data.SQLite .Net provider, and, when I planned it, I took special care with connections and transactions, in order to ensure no connection or transaction was left hanging around.
The tricky part was that setting a breakpoint on ExecuteNonQuery() command and running the application in debug mode would make the error disappear!
Googling, I found something interesting on this site: http://www.softperfect.com/board/read.php?8,5775. There, someone replied the thread suggesting the author to put the database path on the anti-virus ignore list.
I added the database file to the ignore list of my anti-virus (Microsoft Security Essentials) and it solved my problem. No more database locked errors!
Is your database file on the same machine as the app or is it stored on a server?
You should create a new connection in every thread. I would simplefy the creation of a connection, use everywhere: connection = new SQLiteConnection(connString.ToString());
and use a database file on the same machine as the app and test again.
Why the two different ways of creating a connection?
These guys were having similiar problems (mostly, it appears, with the journaling file being locked, maybe TortoiseSVN interactions ... check the referenced articles).
They came up with a set of recommendations (correct directories, changing journaling types from delete to persist, etc). http://sqlite.phxsoftware.com/forums/p/689/5445.aspx#5445
The journal mode options are discussed here: http://www.sqlite.org/pragma.html . You could try TRUNCATE.
Is there a stack trace during the exception into SQL Lite?
You indicate you "batch my commits at a reasonable interval". What is the interval?
I would always use a Connection, Transaction and Command in a using clause. In your first code listing you did, but your third (creating the tables) you didn't. I suggest you do that too, because (who knows?) maybe the commands that create the table somehow continue to lock the file. Long shot... but worth a shot?
Do you have Google Desktop Search (or another file indexer) running? As previously mentioned, Sysinternals Process Monitor can help you track it down.
Also, what is the filename of the database? From PerformanceTuningWindows:
Be VERY, VERY careful what you name your database, especially the extension
For example, if you give all your databases the extension .sdb (SQLite Database, nice name hey? I thought so when I choose it anyway...) you discover that the SDB extension is already associated with APPFIX PACKAGES.
Now, here is the cute part, APPFIX is an executable/package that Windows XP recognizes, and it will, (emphasis mine) ADD THE DATABASE TO THE SYSTEM RESTORE FUNCTIONALITY
This means, stay with me here, every time you write ANYTHING to the database, the Windows XP system thinks a bloody executable has changed and copies your ENTIRE 800 meg database to the system restore directory....
I recommend something like DB or DAT.
While the lock is reported on the COMMIT, the lock is on the INSERT/UPDATE command. Check for record locks not being released earlier in your code.