I have met with the following problem. When the software does not make queries for long time, the connection to the database seems to go into a sleep mode, so that when I do perform a query it needs some time to wake-up.
My solution to that is a timer defined in a static class that every 20 seconds does just this: opens and closes the connection.
My question is, since the timer is asynchronous is my approach thread safe? This is my code.
public static class Db
{
private static string connStr = "";
private static System.Timers.Timer TimerConn = null;
public static void Init(string theconnStr)
{
connStr = theconnStr;
if (TimerConn!=null)
{
TimerConn.Enabled = false;
}
TimerConn = new System.Timers.Timer();
TimerConn.Interval = 20000;
TimerConn.Elapsed += HandleTimerConTick;
TimerConn.Enabled = true;
}
private static void HandleTimerConTick(object source, ElapsedEventArgs e)
{
TestConnection();
}
}
public static bool TestConnection()
{
try
{
SqlConnection con = new SqlConnection(connStr);
con.Open();
con.Close();
return true;
}
catch
{
return false;
}
}
}
Given the only shared state used is the connection string, yes it is thread-safe. If the connection string changes over time (which seems unlikely based on your code) then it may try and connect to an 'old version' of the connection string, but that is the worst behaviour that you might see. This won't be an issue if the connection string never changes.
One thing to consider, to make it slightly cleaner, is to change to:
try
{
using (SqlConnection con = new SqlConnection(connStr))
{
con.Open();
}
return true;
}
catch
{
return false;
}
to remove the need for the explicit Close call.
Note, I am not commenting on whether your code is a good idea. It doesn't seem to be a particularly good idea to be continually connecting and disconnecting from the database like that, but that is outside the scope of your question. I would suggest only reconnecting every three minutes or so though, since normally connections are removed from the pool after four minutes.
Related
I need every thread to connect to one database and execute some query and maybe some thread in one time can execute the query.
I create a static class for connecting to SQL Server database with ADO.NET:
public static class ADOFire
{
static System.Data.SqlClient.SqlConnection Cnn = new System.Data.SqlClient.SqlConnection();
public static string CnnString { get; set; }
public static void CreateConnection()
{
if (Cnn.State == ConnectionState.Open)
return;
Cnn.ConnectionString = CnnString = ConfigurationManager.ConnectionStrings["CnnString"].ToString();
if (Cnn.State != System.Data.ConnectionState.Open)
Cnn.Open();
}
public static System.Data.DataTable GetTable(System.Data.SqlClient.SqlCommand Com, System.Data.SqlClient.SqlDataAdapter Ada, string ComText)
{
CreateConnection();
Com.Connection = Cnn;
Ada.SelectCommand = Com;
try
{
System.Data.DataTable T = new System.Data.DataTable();
Com.CommandText = ComText;
Ada.Fill(T);
return T;
}
catch { return null; }
}
}
And in here in each thread I call static function like this:
System.Data.SqlClient.SqlCommand Com = new System.Data.SqlClient.SqlCommand();
System.Data.SqlClient.SqlDataAdapter Ada = new System.Data.SqlClient.SqlDataAdapter();
Datatable dt = ADOFire.GetTable(Com, Ada, "Some Query 'select * from x'");
Based on this link, doesn't make much difference between open a new connection or use from existing connection
Whenever a user calls Open on a connection, the pooler looks for an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of closing it. Once the connection is returned to the pool, it is ready to be reused on the next Open call
My questions are:
Can a connection serve different threads at the same time? (one connection for all)
Isn't the problem of data clutter due to the static function?
No, ADO.NET does not two threads accessing the same.conection at the same time
Yes, but it isn't the statix method that is a problem - it is the static connection field that is a huge problem
What you should do is have the static method create (new) and return the connection to the caller, and remove the field completely. Typical usage:
using (var conn = CreateConnection()) {
//... Use it!
}
I also have grave concerns about:
- why you're passing in a command and command text and adapter
- the lack of parameters; suggests a huge security problem (SQL injection)
- the use of data table (which is almost never the most appropriate tool)
I am using C# in Visual Studio 2019, with Xamarin.Forms, and SQl in SSMS 2018 and have the below code (where [] is used to replace unneccessary information)
try
{
using(SqlConnection connection = new SqlConnection())
{
connection.ConnectionString = "Server=[ServerName]; Database=[DatabaseName]; User Id= [UserID]; Password=[Password]";
connection.Open();
SqlCommand command = new SqlCommand("SELECT * from [TableName]", connection);
[Does stuff here]
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex)
}
When I run this, it hangs indefinitely at connection.Open(). Debug mode continues to run and appears to move on from Connection.Open(), but never reaches the next line.
I have attempted this with different versions of the ConnectionString, using different databases and with Trusted_Connection=true instead of specifiying the username and password but they have made no difference. Adding Connection Timeout = 5 to the connectionString has no effect.
I believe it is probably an issue with my settings in SQL but as I am a novice with this I have no idea where to start and the similar forums posts I have checked have been given answers along the lines of Connection Timeout (Connection.open for hangs indefinitely, no exception is thrown) or never got answered.
Any advice would be greatly appreciated.
Can you log into SSMS with the credentials that are in the connection string?
Otherwise I've had luck making sure the connection isn't already open or broken first:
if (connection.State == ConnectionState.Closed || connection.State == ConnectionState.Broken)
{
connection.Open();
}
Can you try code changing line as per below -
connection.ConnectionString = "Data Source=[ServerName]; Initial Catalog=[DatabaseName]; Integrated Security=SSPI;"
A workaround to this problem is to pass in a cancellation token instance as shown below,
public async Task<IEnumerable<Toy>> ShowToybox(CancellationToken t)
{
// notice I turned this into an async operation.
// Reason is to let this operation to find its way out if something happens
var connString = "Server=xyz; Connection Timeout=250";
//Timeout might not happen, if that is not the case see below..
using(SqlConnection connection = new SqlConnection(connString))
{
if ( t.IsCancellationRequested) {
t.ThrowIfCancellationRequested();
}
// await query here. To fetch records from the toybox table
return matches;
}
Main issue is that you cannot trust connection.State
To get this working, code that consumes this method should expect something might go wrong.
class Program
{
static void Main()
{
var box = new ToxBox(); //it has method shown above
var s = new CancellationTokenSource();
s.CancelAfter(400); //it prevents method from hanging
var task = Task.Run(() = box.ShowToybox(s.Token));
try
{
task.Wait(s.Token);
var myToys = task.Result();
Console.WriteLine($"I have {myToys.Count()} toys");
}
catch (Exception e)
{
Console.WriteLine("Something happened!");
}
finally
{
s.Dispose(); //this is important
}
}
}
See https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads
I recently solved an issue where my program was crashing while using a BackgroundWorker.
I do not fully understand why there was a problem in the first place. When the thread has it's apartment state set to STA the Process memory increases until the program throws the exception "Unable to allocate environment handle", at first I thought it was an issue with the Database not being able to process the queries quickly enough. The bottom chart on the picture below shows the program running with the thread set to STA. You can see a steady increase in usage until it drops off almost completely. That is when the exception is thrown.
When the thread is running with the ApartmentState set to MTA, the top chart shows it behaving as expected, there is a increase in usage, then it starts a pattern of using and free the memory.
TLDR:
Why does a thread using the Apartment state STA have an issue.
Below I have included some relevant code.
BackgroundWorker myWorkerBee;
List<Customers> AllCustomers
private void btnStartConversion_Click(object sender, RoutedEventArgs e)
{
myWorkerBee = new Thread(myWorkerBee_DoWork);
myWorkerBee.SetApartmentState(ApartmentState.STA);
myWorkerBee.Start();
{
private void myWorkerBee_DoWork()
{
GetOldData(); //Creates Customer object and fills AllCustomers list
AddCustomers();
}
There is no issue with the program if it doesn't use the AddNewCustomerConvert(); Method.
private void AddCustomers()
{
for (int i = 0; i < AllCustomers.Count; i++)
{
AllCustomers[i].AddNewCustomerConvert();
}
}
This method exclusively calls the RawQuery(); Method, or methods that only call the RawQuery(); method
//REFERENCED PROGRAM
AddNewCustomerConvert()
{
//40 or so insert statements.
databaseConnection.RawQuery("//INSERT STATEMENT");
}
Sends Queries to the database
//REFERENCE DLL
public OdbcDataReader RawQuery(string query_to_perform)
{
// This method executes a query in the specific database that you
// are connected to.
System.Data.Odbc.OdbcCommand command = null;
// holds the query sent to the database
System.Data.Odbc.OdbcDataReader result_reader = null;
// The query is put into an OdbcCommand object and sent to the database. The
// return result will then be given back to the caller.
try
{
if (loggingEnabled)
{
myLog = File.AppendText(loggingFileName);
myLog.WriteLine(query_to_perform);
myLog.Close();
myLog.Dispose();
}
command = new System.Data.Odbc.OdbcCommand(query_to_perform, this.database_connection);
result_reader = command.ExecuteReader();
this.successful_query = true;
this.error_message = "";
}
catch (System.Data.Odbc.OdbcException ex)
{
this.successful_query = false;
this.error_message = ex.Message;
//destroy the connection on a failure
database_connection = new OdbcConnection();
throw;
}
return result_reader;
}
Does anyone have a solid pattern fetching Redis via BookSleeve library?
I mean:
BookSleeve's author #MarcGravell recommends not to open & close the connection every time, but rather maintain one connection throughout the app. But how can you handle network breaks? i.e. the connection might be opened successfully in the first place, but when some code tries to read/write to Redis, there is the possibility that the connection has dropped and you must reopen it (and fail gracefully if it won't open - but that is up to your design needs.)
I seek for code snippet(s) that cover general Redis connection opening, and a general 'alive' check (+ optional awake if not alive) that would be used before each read/write.
This question suggests a nice attitude to the problem, but it's only partial (it does not recover a lost connection, for example), and the accepted answer to that question draws the right way but does not demonstrate concrete code.
I hope this thread will get solid answers and eventually become a sort of a Wiki with regards to BookSleeve use in .Net applications.
-----------------------------
IMPORTANT UPDATE (21/3/2014):
-----------------------------
Marc Gravell (#MarcGravell) / Stack Exchange have recently released the StackExchange.Redis library that ultimately replaces Booksleeve. This new library, among other things, internally handles reconnections and renders my question redundant (that is, it's not redundant for Booksleeve nor my answer below, but I guess the best way going forward is to start using the new StackExchange.Redis library).
Since I haven't got any good answers, I came up with this solution (BTW thanks #Simon and #Alex for your answers!).
I want to share it with all of the community as a reference. Of course, any corrections will be highly appreciated.
using System;
using System.Net.Sockets;
using BookSleeve;
namespace Redis
{
public sealed class RedisConnectionGateway
{
private const string RedisConnectionFailed = "Redis connection failed.";
private RedisConnection _connection;
private static volatile RedisConnectionGateway _instance;
private static object syncLock = new object();
private static object syncConnectionLock = new object();
public static RedisConnectionGateway Current
{
get
{
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
{
_instance = new RedisConnectionGateway();
}
}
}
return _instance;
}
}
private RedisConnectionGateway()
{
_connection = getNewConnection();
}
private static RedisConnection getNewConnection()
{
return new RedisConnection("127.0.0.1" /* change with config value of course */, syncTimeout: 5000, ioTimeout: 5000);
}
public RedisConnection GetConnection()
{
lock (syncConnectionLock)
{
if (_connection == null)
_connection = getNewConnection();
if (_connection.State == RedisConnectionBase.ConnectionState.Opening)
return _connection;
if (_connection.State == RedisConnectionBase.ConnectionState.Closing || _connection.State == RedisConnectionBase.ConnectionState.Closed)
{
try
{
_connection = getNewConnection();
}
catch (Exception ex)
{
throw new Exception(RedisConnectionFailed, ex);
}
}
if (_connection.State == RedisConnectionBase.ConnectionState.Shiny)
{
try
{
var openAsync = _connection.Open();
_connection.Wait(openAsync);
}
catch (SocketException ex)
{
throw new Exception(RedisConnectionFailed, ex);
}
}
return _connection;
}
}
}
}
With other systems (such as ADO.NET), this is achieved using a connection pool. You never really get a new Connection object, but in fact get one from the pool.
The pool itself manages new connections, and dead connections, independently from caller's code. The idea here is to have better performance (establishing a new connection is costy), and survive network problems (the caller code will fail while the server is down but resume when it comes back online). There is in fact one pool per AppDomain, per "type" of connection.
This behavior transpires when you look at ADO.NET connection strings. For example SQL Server connection string (ConnectionString Property) has the notion of 'Pooling', 'Max Pool Size', 'Min Pool Size', etc. This is also a ClearAllPools method that is used to programmaticaly reset the current AppDomain pools if needed for example.
I don't see anything close to this kind of feature looking into BookSleeve code, but it seems to be planned for next release: BookSleeve RoadMap.
In the mean time, I suppose you can write your own connection pool as the RedisConnection has an Error Event you can use for this, to detect when it's dead.
I'm not a C# programmer, but the way I'd look at the problem is the following:
I'd code a generic function that would take as parameters the redis connection and a lambda expression representing the Redis command
if trying to execute the Redis command would result in an exception pointing out a connectivity issue, I've re-initialize the connection and retry the operation
if no exception is raised just return the result
Here is some sort of pseudo-code:
function execute(redis_con, lambda_func) {
try {
return lambda_func(redis_con)
}
catch(connection_exception) {
redis_con = reconnect()
return lambda_func(redis_con)
}
}
So what i'm looking to do is open a MysqlConnection and then never close it for the entire application (until the end).
I have this:
static void Main(string[] args)
{
OpenCon();
}
public static MySqlConnection OpenCon()
{
MySqlConnection masterOpenCON = new MySqlConnection(SQLStringClass.masterConString);
masterOpenCON.Open();
return masterOpenCON;
}
However, i believe this will continuously open the connect, how do i open the connection once and reference the connection throughout the app. This is how I am calling it right now.
try
{
MySqlCommand mysqlprocessCmdInsertItem = new MySqlCommand(SQLStringClass.mySQLCOMMAND, OpenCon());
mysqlprocessCmdInsertItem.ExecuteNonQuery();
}
Don't bother with this. The MySQL ADO.NET Connector uses a pool of connections meaning that when you call .Open on a connection you are not actually opening it, you are drawing it from the existing connection pool and when you call .Close you are not closing it, you are returning it to the connection pool so that it can be reused.
IIRC connection pooling is enabled by default but you could control it with the following parameters on your connection string:
Pooling = true
Max Pool Size = 100
Min Pool Size = 0
So when you want to send a SQL query all you need to do is the following and let the ADO.NET framework worry about connections:
using (var conn = new MySqlConnection(SQLStringClass.masterConString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT Foo FROM Bar";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
...
}
}
}
I would recommend you avoiding any static members and manual connection handling.
You need to store the connection in a static field or property.
For example:
public static MySqlConnection Connection { get; private set; }
Connection = OpenCon();
You need to also specify the connection object as static.
private static MySqlConnection masterOpenCON;
static void Main(string[] args)
{
OpenCon();
}
public static MySqlConnection OpenCon()
{
masterOpenCON = new MySqlConnection(SQLStringClass.masterConString);
masterOpenCON.Open();
return masterOpenCON;
}