How to access DB in asp.net on this scenario? - c#

Hello Guys Below is my Code for accessing database. when i try to open site from more than one tab or i open it in debugging mode it gives error!
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace DomeNameSpace
{
public class DAL
{
public static string _ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["xClassConnectionString"].ConnectionString;
public static SqlConnection _Connection = null;
public static SqlConnection Connection
{
get
{
//_Connection.Close();
//private static SqlConnection _Connection = null;
if (_Connection == null)
{
_Connection = new SqlConnection(_ConnectionString);
_Connection.Open();
return _Connection;
}
else if (_Connection.State != System.Data.ConnectionState.Open)
{
_Connection.Open();
return _Connection;
}
else
{
return _Connection;
}
}
}
public static DataSet GetDataSet(string sql)
{
try
{
SqlCommand cmd = new SqlCommand(sql, Connection);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
// Connection.Close();
DataSet ds = new DataSet();
adp.Fill(ds);
return ds;
}
catch (SqlException err)
{
// Replace the error with something less specific.
// You could also log the error now.
throw new ApplicationException("Data error. " + err.Message.ToString());
}
finally
{
Connection.Close();
}
}
public static DataTable GetDataTable(string sql)
{
DataSet ds = GetDataSet(sql);
if (ds.Tables.Count > 0)
return ds.Tables[0];
return null;
}
public static int ExecuteSQL(string sql)
{
try
{
string BegSql = "BEGIN TRY BEGIN TRANSACTION ";
string EndSql = " COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION END CATCH";
string NewSql = BegSql + sql + EndSql;
sql = NewSql;
SqlCommand cmd = new SqlCommand(sql, Connection);
return cmd.ExecuteNonQuery();
}
catch (System.Exception ex)
{
return -1;
}
finally
{
Connection.Close();
}
}
}
}
But i am getting following here error
and output says
what seems to be the problem?

A single, static database connection is a famously bad idea. It essentially makes your application single-threaded, which a web application by nature is not.
Don't centralize your connection object like this. Creating a connection object is not a resource-intensive operation. And opening the connection itself isn't particularly resource-intensive, the connection pool takes care of most of the heavy lifting for you and is very well optimized.
Create your database connection objects when you need them, as close to where you use them as possible, and dispose of them as soon as you're done with them. In general, a pattern similar to this:
public void SomeMethodWhichConnectsToDB()
{
using (var connection = new SqlConnection())
using (var command = new SqlCommand())
{
// do something with the connection, execute the command, etc
}
}
You can encapsulate the creation of the connection into a (non-static) method to avoid code duplication and whatnot. But don't re-use the same connection object in memory over and over. Create it, use it, destroy it in as little time as possible.

The error is pretty self-explanatory but the reason you are running into this sort of problem is because the connection object is static, which means, that you are sharing this instance for all the calls you make to the database - all threads executing any kind of data access will use the same connection, which you clearly don't want.
What you should do is create the instance of a SQL Connection inside every method or create a Utility class that returns a new instance for every call.
For example:
public class DBUtility
{
public static DbConnection GetOpenConnection()
{
var conn = new DBConnection(connectionString); //or whatever type
conn.Open();
return conn;
}
}
Now in your methods:
public static int ExecuteSQL(string sql)
{
using (var conn = DBUtility.GetOpenConnection())
{
....
}
}

Related

Best way to create new SqlConnection when is null

I have two methods that connect to the database and I try to avoid double code
one of my methods is one that can run alon (open itself SqlConnection and close it)
another method using existing SqlConnection and using SqlTransaction also (I don't want to open another connection and also I don't want to close it)
my first method :
public static List<CSerieses> GetCSerieses(DeliveryReportObject DeliveryReportObject)
{
List<CSerieses> CSerieses = new List<CSerieses>();
try
{
using (SqlConnection openCon = new SqlConnection(connectionString))
{
string query = "SELECT [CSeriesNum],[CCount],[Mark] from [Serieses] " +
"where [TestPrimary]=#deliveryNumber";
SqlCommand command = new SqlCommand(query, openCon);
command.Parameters.AddWithValue("#deliveryNumber", DeliveryReportObject.DeliveryNumber);
openCon.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
CSerieses.Add(new CSerieses(reader.GetString(0), reader.GetInt32(1), reader.GetBoolean(2)));
}
}
openCon.Close();
}
}
catch (Exception ex)
{
LocalPulserDBManagerInstance.WriteLog(ex.StackTrace, ex.Message);
}
return CSerieses;
}
The method that using on the transaction :
public static List<CSerieses> GetCSerieses(DeliveryReportObject DeliveryReportObject,
SqlConnection co,SqlTransaction tran)
{
List<CSerieses> CSerieses = new List<CSerieses>();
try
{
using (co)
{
string query = "SELECT [CSeriesNum],[CCount],[Mark] from [Serieses] " +
"where [TestPrimary]=#deliveryNumber";
SqlCommand command = new SqlCommand(query, co, tran);
command.Parameters.AddWithValue("#deliveryNumber", DeliveryReportObject.DeliveryNumber);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
CSerieses.Add(new CSerieses(reader.GetString(0), reader.GetInt32(1), reader.GetBoolean(2)));
}
}
}
}
catch (Exception ex)
{
LocalPulserDBManagerInstance.WriteLog(ex.StackTrace, ex.Message);
}
return CSerieses;
}
I try to combine them :
public static List<CSerieses> GetCSerieses(DeliveryReportObject DeliveryReportObject,
SqlConnection co = null,SqlTransaction tran = null)
{
List<CSerieses> CSerieses = new List<CSerieses>();
try
{
using (co ?? new SqlConnection(connectionString))
{
if (co.IsOpened() == false)
{
co.Open();
}
string query = "SELECT [CSeriesNum],[CCount],[Mark] from [Serieses] " +
"where [TestPrimary]=#deliveryNumber";
SqlCommand command = new SqlCommand(query, co, tran);
if(tran != null)
{
command.Transaction = tran;
}
command.Parameters.AddWithValue("#deliveryNumber", DeliveryReportObject.DeliveryNumber);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
CSerieses.Add(new CSerieses(reader.GetString(0), reader.GetInt32(1), reader.GetBoolean(2)));
}
}
}
}
catch (Exception ex)
{
LocalPulserDBManagerInstance.WriteLog(ex.StackTrace, ex.Message);
}
return CSerieses;
}
It does not work for me. I have no idea how to check if it null in using and if yes to create a new instance of SqlConnection that should close at the end of the using statement
And I do it the right way anyway?
This is a major problem:
using (co ?? new SqlConnection(connectionString))
If co is passed in, then you don't own it - the caller does - so: you shouldn't be disposing it. What I would suggest here is:
bool ownConnection = false;
try
{
if (co is null)
{
ownConnection = true;
co = new SqlConnection(...);
co.Open();
}
// your code here
}
finally
{
if (ownConnection)
{
co?.Dispose();
}
}
or wrap that up in a helper - perhaps a custom disposable that takes a connection and connection string:
public readonly struct ConnectionWrapper : IDisposable
{
private readonly bool owned;
public SqlConnection Connection { get; }
public ConnectionWrapper(SqlConnection connection, string connectionString)
{
if (connection is null)
{
owned = true;
Connection = new SqlConnection(connectionString);
Connection.Open();
}
else
{
owned = false;
Connection = connection;
}
}
public void Dispose()
{
if (owned)
{
Connection?.Dispose();
}
}
}
then you can just use:
using var wrapped = new ConnectionWrapper(co, connectionString);
// your code, using wrapped.Connection
This seems that kind of situation that perfectly fits the overload concept.
The GetCSerieses method should have two versions, the first one builds its own connection and transaction, the second one takes both a non optional connection and a non optional transaction. The first one, after creating the connection and the transaction calls the second one.
Now if a third method requires a call the GetCSerieses could pass its own connection and transaction, while a call without them will be handled by the first overload
public static List<CSerieses> GetCSerieses(DeliveryReportObject DeliveryReportObject)
{
using(SqlConnection con = new SqlConnection(......))
{
try
{
con.Open();
using(SqlTransaction tran = con.BeginTransaction())
{
return GetCSerieses(DeliveryReportObject, con, tran);
}
// Or, if you don't need a transaction you could call the
// overload passing null
// return GetCSerieses(DeliveryReportObject, con, null);
}
catch(Exception ex)
{
LocalPulserDBManagerInstance.WriteLog(ex.StackTrace, ex.Message);
return null; // ?? or return new List<CSerieses>();
}
}
}
public static List<CSerieses> GetCSerieses(DeliveryReportObject DeliveryReportObject, SqlConnection co, SqlTransaction tran)
{
List<CSerieses> CSerieses = new List<CSerieses>();
try
{
// We don't own the connection and the transaction object.
// Whoever passed them to us is responsible of their disposal.
string query = "......";
SqlCommand command = new SqlCommand(query, co, tran);
command.Transaction = tran;
....
}
catch (Exception ex)
{
LocalPulserDBManagerInstance.WriteLog(ex.StackTrace, ex.Message);
}
return CSerieses;
}

Passing Connection From TableAdapter Produces connectionstring property has not been initialized

I ran into a problem where passing a connection from a TableAdapter to some methods throws an exception stating the connectionstring isn't initialized. There are quite a few questions on SO with this exception but none were passing the connection and most were because the ConnectionString was null. Weird thing is I used MessageBox.Show(connection.ConnectionString); through out the chain of methods and I receive a valid connection string at every step. This is a somewhat complicated program that is in production but I will try to simplify the code for this question...
This is the postInventoryData method, which takes a DataGridView with inventory items and iterates through it posting them to the inventory. I use a TransactionScope to ensure the changes are safely rolled back in the event of an error. If an item is a kit(an item comprised of other items) I must iterate through those items and remove them from the inventory. The problem occurs when I check whether or not the item is a kit.
public bool postInventoryData(DataGridView dgv)
{
bool successful = true;
TestDataSetTableAdapters.inentoryTrxTableAdapter inventoryTrxAdapter =
new TestDataSetTableAdapters.inentoryTrxTableAdapter();
try
{
using (TransactionScope trxScope = new TransactionScope
(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0)))
{
MessageBox.Show(inventoryTrxAdapter.Connection.ConnectionString); // <-- Valid ConnectionString
inventoryTrxAdapter.OpenConnection();
for (int i = 0; i < dgv.Rows.Count; i++)
{
//parameter values
string departmentCode = dgv.Rows[i].Cells["Department_Code"].Value.ToString();
string machineCode = dgv.Rows[i].Cells["Machine_Code"].Value.ToString();
string operatorCode = dgv.Rows[i].Cells["Operator_Code"].Value.ToString();
string itemNumber = dgv.Rows[i].Cells["Item_Number"].Value.ToString();
double? qtyProduced = Convert.ToDouble(dgv.Rows[i].Cells["Quantity"].Value.ToString());
bool isKit =
businessLayer.isItemNumberKit
(inventoryTrxAdapter.Connection, itemNumber); // <-- CULPRIT!
// Inserts the item
dailyProductionInsertQty(
departmentCode,
machineCode,
operatorCode,
itemNumber,
isKit,
qtyProduced,
inventoryTrxAdapter,
trxScope);
}
inventoryTrxAdapter.CloseConnection();
trxScope.Complete();
}
}
catch (System.Exception ex)
{
successful = false;
MessageBox.Show(ex.ToString());
}
return successful;
}
The isItemNumberKit method
public bool isItemNumberKit(SqlConnection connection, string itemNumber)
{
bool contains;
MessageBox.Show(connection.ConnectionString); // <-- Valid ConnectionString
DataTable dt = getKit(connection, itemNumber); // <-- CULPRIT!
if (dt.Rows.Count > 0)
{
contains = true;
}
else
{
contains = false;
}
return contains;
}
The getKit method
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString); // <-- Valid ConnectionString
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
using (myConnection)
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
When I execute postInventoryData the program throws an exception with the message, "The connectionstring property has not been initialized." with the line numbers pointing to isItemNumberKit and getKit. As you can see in the code above, I used a MessageBox.Show(connection.ConnectionString) throughout the process and each time I received a valid Connection string. I have created a workaround which stores a cached DataTable containing all the kit items I can run linq statements on. I am not in emergency mode or anything but I thought this to be weird and an opportunity for me to learn. Thanks in advance for any help!
It might be possible that you have 2 app.config files in your solution with 2 different connection strings.
OK, I figured it out and now when I think about it the answer was somewhat obvious. I always use using(){} blocks to ensure connections and similar objects are properly disposed and taken care of after they are used. The solution was to simply remove the using(myConnection){} block from the getKit method like this:
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString);
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber
";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
This will leave the connection intact but properly dispose of the command. Sorry for the long winded question with a short simple answer. Hope this might help someone someday.

DB Connection issue only some times

I have a problem with the below code,There's no any coding error BUT sometimes it throws some exceptions.I just wanted to know any code organizing issue ? & how to fix it.
Sometimes it shows those exceptions
1.ExecuteReader requires an open and available Connection. The connection's current state is closed.
2.Invalid attempt to call FieldCount when reader is closed.
But Sometimes it works without any issue,as expected
My Coding Goes here
[WebMethod, ScriptMethod]
public static List<HomeImageSliders> GetHomeImageSliders()
{
List<HomeImageSliders> HomeImageList = new List<HomeImageSliders>();
try
{
SqlCommand comHomeImage = new SqlCommand("SP_GetHomeImageSliders", conDB);
comHomeImage.CommandType = CommandType.StoredProcedure;
if (conDB.State != ConnectionState.Open)
{
conDB.Open();
}
SqlDataReader rdr = comHomeImage.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rdr);
foreach (DataRow r in dt.Rows)
{
HomeImageList.Add(new HomeImageSliders
{
Id = (int)r["Id"],
ImagePath = r["ImagePath"].ToString(),
ModifiedDate = Convert.ToDateTime(r["ModifiedDate"]).Date
});
}
}
catch (Exception ee)
{
}
finally
{
conDB.Close();
}
return HomeImageList;
}
You should use the "using" construction:
(using ommand comHomeImage = new SqlCommand("SP_GetHomeImageSliders", conDB) {
(using SqlDataReader rdr = new SqlDataReader) {
//do some things
}
}
I don't know why your connection sometimes is closed when you call
ExecuteReader()
But why don't you use a using block instead like this:
using(SqlConnection conDB = new SqlConnection(connectionString))
{
...
}
this will close your connection to the DB when it loses scope.
try to prevent using the same connection with two or more threads by usinglock 
lock(_conDb)
{
//// your code here
}
and also wrap your conDb in using block as below
using(SqlConnection conDB = new SqlConnection(connectionString))
{
...
}

SQLite Database Locked exception

I am getting Database is locked exception from SQLite for some queries only.
Below is my code:
When I execute any select statement it works fine.
When I am executing any write statement on Jobs Table it also works fine.
This works fine:
ExecuteNonQuery("DELETE FROM Jobs WHERE id=1");
But the same way if I am executing queries for Employees table it is throwing an exception that database is locked.
This throws Exception:
ExecuteNonQuery("DELETE FROM Employees WHERE id=1");
Below are my functions:
public bool OpenConnection()
{
if (Con == null)
{
Con = new SQLiteConnection(ConnectionString);
}
if (Con.State == ConnectionState.Closed)
{
Con.Open();
//Cmd = new SQLiteCommand("PRAGMA FOREIGN_KEYS=ON", Con);
//Cmd.ExecuteNonQuery();
//Cmd.Dispose();
//Cmd=null;
return true;
}
if (IsConnectionBusy())
{
Msg.Log(new Exception("Connection busy"));
}
return false;
}
public Boolean CloseConnection()
{
if (Con != null && Con.State == ConnectionState.Open)
{
if (Cmd != null) Cmd.Dispose();
Cmd = null;
Con.Close();
return true;
}
return false;
}
public Boolean ExecuteNonQuery(string sql)
{
if (sql == null) return false;
try
{
if (!OpenConnection())
return false;
else
{
//Tx = Con.BeginTransaction(IsolationLevel.ReadCommitted);
Cmd = new SQLiteCommand(sql, Con);
Cmd.ExecuteNonQuery();
//Tx.Commit();
return true;
}
}
catch (Exception exception)
{
//Tx.Rollback();
Msg.Log(exception);
return false;
}
finally
{
CloseConnection();
}
}
This is the Exception:
At line 103 : Cmd.ExecuteNonQuery();
Exception Found:
Type: System.Data.SQLite.SQLiteException
Message: database is locked
database is locked
Source: System.Data.SQLite
Stacktrace: at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
at System.Data.SQLite.SQLiteDataReader.NextResult()
at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
at TimeSheet6.DbOp.ExecuteNonQuery(String sql) in d:\Projects\C# Applications\Completed Projects\TimeSheet6\TimeSheet6\DbOp.cs:line 103
Somewhere along the way a connection is getting left open. Get rid of OpenConnection and CloseConnection and change ExecuteNonQuery to this:
using (SQLiteConnection c = new SQLiteConnection(ConnectionString))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
}
Further, change the way you read data to this:
using (SQLiteConnection c = new SQLiteConnection(ConnectionString))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
...
}
}
}
Do not attempt, to manage connection pooling on your own like you are here. First, it's much more complex than what you have coded, but second, it's handled already inside the SQLiteConnection object. Finally, if you're not leveraging using, you're not disposing these objects properly and you end up with issues like what you're seeing now.
You can use 'using' statement as below, that will make sure connection & command disposed correctly even in exception
private static void ExecuteNonQuery(string queryString)
{
using (var connection = new SQLiteConnection(
ConnectionString))
{
using (var command = new SQLiteCommand(queryString, connection))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
}
}
You should close your DataReader before attempting to write any data to the database. Use:
dr.Close();
after you finish using the DataReader.
In my case it was very stupid of me, I was making changes in 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 request worked as expected.
A lot of helpful posts here for folks that may have forgotten to clean up a dangling connection, but there is another way this can happen: SQLite does not support concurrent INSERTs; if you issue two INSERTs at the same time the will be processed in serial. When the INSERTs are quick this is fine, but if an INSERT takes longer than the timeout the second INSERT can fail with this message.
I had this happen when I used a long running transaction to accumulate a bunch of INSERTs into one big commit. Basically I locked the database from any other activity during the transaction. Switching to journal_mode=WAL will allow concurrent writes and reads, but not concurrent writes.
I got rid of the long running transaction and let each INSERT autocommit, and that solved my problem.
Mine was caused by not closing a SqliteDataReader when calling HasRows().
I had this:
using (SQLiteConnection connection = new SQLiteConnection(DbPath))
{
connection.Open();
string sql = $"SELECT * FROM ...";
using (SQLiteCommand command = new SQLiteCommand(sql, connection))
{
return command.ExecuteReader().HasRows;
}
connection.Close();
}
But needed to put a using around the ExecuteReader like so:
using (SQLiteDataReader reader = command.ExecuteReader())
{
return command.ExecuteReader().HasRows;
}
Even though the DbConnection was being disposed and re-created each time the db was still being kept locked by the reader.
I was also getting the same error here:
if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true)
{
SQLiteConnection m_dbConnection = new SQLiteConnection(MainWindow.con);
m_dbConnection.Open();
sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id;
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
m_dbConnection.Close();
LoadUserDG();
}
but when I just changed SQLiteConnection declaration location
public partial class User : Window
{
SQLiteCommand command;
string sql;
AddUser AddUserObj;
List<basics.users> usersList;
basics.users SelectedUser;
SQLiteConnection m_dbConnection;
// ...
private void DeleteBtn_Click(object sender, RoutedEventArgs e)
{
// ...
if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true)
{
m_dbConnection = new SQLiteConnection(MainWindow.con);
m_dbConnection.Open();
sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id;
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
m_dbConnection.Close();
LoadUserDG();
}
}
Everything is fine now.
I hope this may work for you, too.
If someone can say how this happened, I would like to know the details to improve my knowledge, please.
I had the same issue when loading a lot of data to different tables from multiple threads.
When trying to do the inserts I was getting database locked because the program was doing too many insert too fast and SQLite didn't have time to complete each transaction before another one came.
The insert are done through threading because I didn't want the interface to be locked and wait for the insert to be done.
My solution is to use BlockingCollection with ThreadPool.QueueUserWorkItem.
This allows me to free the interface while doing the inserts.
All the insert are queued and executed in FIFO (First In First Out) order.
Now the database is never locked while doing any SQL transaction from any thread.
public class DatabaseQueueBus
{
private BlockingCollection<TransportBean> _dbQueueBus = new BlockingCollection<TransportBean>(new ConcurrentQueue<TransportBean>());
private CancellationTokenSource __dbQueueBusCancelToken;
public CancellationTokenSource _dbQueueBusCancelToken { get => __dbQueueBusCancelToken; set => __dbQueueBusCancelToken = value; }
public DatabaseQueueBus()
{
_dbQueueBusCancelToken = new CancellationTokenSource();
DatabaseQueue();
}
public void AddJob(TransportBean dto)
{
_dbQueueBus.Add(dto);
}
private void DatabaseQueue()
{
ThreadPool.QueueUserWorkItem((param) =>
{
try
{
do
{
string job = "";
TransportBean dto = _dbQueueBus.Take(_dbQueueBusCancelToken.Token);
try
{
job = (string)dto.DictionaryTransBean["job"];
switch (job)
{
case "SaveClasse":
//Save to table here
break;
case "SaveRegistrant":
//Save Registrant here
break;
}
}
catch (Exception ex)
{//TODO: Handle this exception or not
}
} while (_dbQueueBusCancelToken.Token.IsCancellationRequested != true);
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
}
});
}
}
The inserts are done this way, but without the queuing I was still getting the lock issue.
using (SQLiteConnection c = new SQLiteConnection(BaseDal.SQLiteCon))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
c.Close();
}

Getting a connection to database lost error

every once and a while my application throws a connection to database lost error.
The database class I got from a tutorial site and is below, it works great except for the above error sometimes, im guessing its timing out, like if the person using it goes for a smoke break and comes back and tries to continue where they left off.
And of coarse being the normal end-user they close then error message THEN come get me to tell me they got an error.
But until the error comes up again i thought i would ask what part of this code could be changed to prevent that error
this is a firebird db server and a c# application
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Windows.Forms;
using FirebirdSql.Data.FirebirdClient;
namespace _0912111
{
class DatabaseConnection
{
private FbConnection conn;
private FbCommand sqlCommand;
private FbDataAdapter DB;
private DataSet DS = new DataSet();
public DatabaseConnection()
{
conn = new FbConnection("User=myuser;" + "Password=mypw;" + "Database=dbpath;" + "DataSource=serverip;" + "Port=dbport;" + "Dialect=3;" + "Charset=UTF8;");
}
public void showDbError(string theError)
{
MessageBox.Show("Could not connect to database\n\nError Details:\n" + theError);
}
public FbConnection Openconn()
{
if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken)
{
try
{
conn.Open();
}
catch (Exception e)
{
showDbError(e.Message.ToString());
}
}
return conn;
}
public FbConnection Closeconn()
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
return conn;
}
public void nonQuery(string txtQuery)
{
FbCommand cmd = new FbCommand(txtQuery);
try
{
cmd.Connection = Openconn();
cmd.ExecuteNonQuery();
}
catch (Exception Ex)
{
showDbError(Ex.Message.ToString());
throw Ex;
}
finally
{
cmd = null;
}
}
public FbDataReader returnDataReader(string txtQuery)
{
FbCommand cmd = new FbCommand();
try
{
cmd.Connection = Openconn();
cmd.CommandText = txtQuery;
FbDataReader rd;
rd = cmd.ExecuteReader();
return rd;
}
catch (Exception Ex)
{
showDbError(Ex.Message.ToString());
throw Ex;
}
finally
{
cmd = null;
}
}
}
}
I would think that the code in her that says
if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken)
{
would prevent it??
Look, I suggest you to use using and rewrite your methods in a cleaner way, no reason to have another method to open and another to close connection, I'm not doing it anymore since longer than 5 years :D
also, no reason to do a ToString() on Ex.Message and also, notice, in C# you should throw exceptions with only throw not throw exc.
one of your methods would become this for example:
public void nonQuery(string txtQuery)
{
using(var conn = new FbConnection(GetMyConnectionString(...parameters...)))
{
using(var cmd = new FbCommand(txtQuery))
{
try
{
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
showDbError(ex.Message);
throw;
}
}
}
}
I'm 100% with Davide Piras on this. (upvoted him)
Delete the "Openconn" and "Closeconn" methods from your DatabaseConnection class. Then change your queries to have using statements for the connection open and command execution.
The database drivers already know how to perform connection pooling. Maintaining an open connection in code is not just a waste of time, but a potential cause of issues like the one you are experiencing. Other issues it can cause are leaked memory and the ability to open further connections with the database server.
So, rewrite your code to use best practices for database access and the problem will go away.
I'll leave this example that speaks of the connection and some examples that I hope will help.
http://code.msdn.microsoft.com/Esempio-applicazione-dati-494c129a
Regards.

Categories

Resources