I am having some problems to handle the connection to a database. What I did essentially was to create a class called Database, in this I placed all the methods required to connect to the database, check whether the connection is active and update a control depending on the status of the connection. This works well, control is updated and there are no problems, but when the connection on your computer is absent, the program delays its opening because they generated a series of exceptions in particular that:
MySql.Data.MySqlClient.MySqlException (0x80004005)
The exception occurs in the method isAvailable(), this method checks whether the connection is available or not, and returns true if there is, respectively, or false if it is absent.
public static bool isAvailable()
{
try
{
string connStr = #"Server=xxx;Port=xxx;Database=xxx;Uid=xxx;Pwd=xxx;";
connection = new MySqlConnection(connStr);
connection.Open();
return true;
}catch(Exception ex)
{
connection.Close();
Console.WriteLine(ex.ToString());
return false;
}
}
This method is invoked by checkStatus that contains the following:
public static void checkStatus()
{
if(isAvailable() == false)
{
updateStatus("false");
}
else
{
updateStatus("true");
}
}
checks whether it is true or false and returned respectively to the back passes the value to another method that simply brings up a warning Canvas red or green in the interface ...
checkStatus is called in every aspect of my other classes to check the connection status (before executing a query, pretty much the structure is as follows):
string stm = "SELECT * FROM history";
MySqlCommand cmd = new MySqlCommand(stm, Database.Database.Connection);
Database.Database.checkStatus(); //here
MySqlDataReader rdr = cmd.ExecuteReader();
Within the class constructor call the method isAvailable Database to check if the connection is actually open or not.
At this point I do not understand why the exceptions while managing the program delays the appearance when the user executes it. If no exceptions occur when you start, the program takes about 5 seconds to boot, while with the exceptions I arrived at 1 minute!
What am I doing wrong?
Making a connection to the database server may take quite some time due to many factors: network conditions, server load, authentication overhead etc. Hence the driver (the code behind MySqlConnection) needs to wait an appropriate amount of time to decide whether the connection can or cannot be established. The default timeout is, apparently in your case, 60 seconds (or a multiple of the default 15 seconds as per documentation due to several requests?).
What you can do is lower the timeout by means of the ConnectionTimeout argument in the connection string — see the documentation here. However, bear in mind that by setting it to, say, 5 seconds, you program may end up failing in legitimate cases where it would otherwise succcessfuly connect to the server. I suggest you perform database operations or at least the initial check asynchronously and display a 'please wait' message meanwhile.
Related
For my data access I use TransactionScopes at the API level to wrap entire operations in a single transaction so that my SQL operations can be somewhat composable. I have a web project that hosts an API and a separate service library that is the implementation and calls to SQL. At the beginning of an Operation (an API entry-point) I open the TransactionScope. Whenever a SqlConnection is needed within the processing of the Operation, ask for the AmbientConnection instead of directly making a new connection. AmbientConnection finds or creates a new SqlConnection for the current transation. Doing this is supposed to allow for good composibility but also avoid the invocation of the MSDTC because it should keep using the same connection for the each suboperation within the transaction. When the transaction is completed (with scope.complete()), the connection is automatically closed.
The problem is that every once in a while the MSDTC is still getting invoked and I cannot figure out why. I've used this before sucessfully and I believe I never got an MSDTC invoked. Two things seem different to me this time though: 1) I'm using SQL Server 2008 R1 (10.50.4000) - not my choice - and I'm aware that the MSDTC behavior changed beginning with this version and perhaps not all the kinks were worked out until later versions. 2) The use of async-await is new and I believe I'm having to use TransactionScopeAsyncFlowOption.Enabled to accommodate this new feature in case some part of the implementation is async. Perhaps more measures are necessary.
I tried Pooling=false in the connection string in case it was MSDTC getting invoked because of two independent logical connections handled errantly under a single pooled connection. But that didn't work.
API Operation
// Exposed API composing multiple low-level operations within a single TransactionScope
// independent of any database platform specifics.
[HttpPost]
public async Task<IHttpActionResult> GetMeTheTwoThings()
{
using (var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled))
{
var result = new TwoThings(
await serviceLayer.GetThingOne(),
await serviceLayer.GetThingTwo());
scope.Complete();
return Ok(result);
}
}
Service layer implementation
public async Task<ThingOne> GetThingOne()
{
using (var cmd = connManagement.AmbientConnection.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "dbo.GetThingOne";
return (ThingOne)(await cmd.ExecuteScalarAsync());
}
}
public async Task<ThingTwo> GetThingTwo()
{
using (var cmd = connManagement.AmbientConnection.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "dbo.GetThingTwo";
return (ThingTwo)(await cmd.ExecuteScalarAsync());
}
}
AmbientConnection implementation
internal class SQLConnManagement
{
readonly string connStr;
readonly ConcurrentDictionary<Transaction, SqlConnection> txConnections = new ConcurrentDictionary<Transaction, SqlConnection>();
private SqlConnection CreateConnection(Transaction tx)
{
var conn = new SqlConnection(this.connStr);
// When the transaction completes, close the connection as well
tx.TransactionCompleted += (s, e) =>
{
SqlConnection closing_conn;
if (txConnections.TryRemove(e.Transaction, out closing_conn))
{
closing_conn.Dispose(); // closing_conn == conn
}
};
conn.Open();
return conn;
}
internal SqlConnection AmbientConnection
{
get
{
var txCurrent = Transaction.Current;
if (txCurrent == null) throw new InvalidOperationException("An ambient transaction is required.");
return txConnections.GetOrAdd(txCurrent, CreateConnection);
}
}
public SQLConnManagement(string connStr)
{
this.connStr = connStr;
}
}
Not to overcomplicate the post, but this might be relevant because it seems to me that every time MSDTC has been invoked the logged stack trace shows that this next mechanism has been involved. Certain data I cache with the built in ObjetCache because it doesn't change often and so I just get it at most once per minute or whatever. This is a little fancy, but I don't see why the Lazy generator would be treated any differently from a more typical call and why this specifically would cause the MSSDTC to sometimes be invoked. I've tried LazyThreadSafetyMode.ExecutionAndPublication too just in case but that doesn't help anyway (and then the exception just keeps getting delivered as the cached result for subsequent requests before the expiration, of course, and that's not desirable).
/// <summary>
/// Cache element that gets the item by key, or if it is missing, creates, caches, and returns the item
/// </summary>
static T CacheGetWithGenerate<T>(ObjectCache cache, string key, Func<T> generator, DateTimeOffset offset) where T : class
{
var generatorWrapped = new Lazy<T>(generator, System.Threading.LazyThreadSafetyMode.PublicationOnly);
return ((Lazy<T>)cache.AddOrGetExisting(
key,
generatorWrapped,
offset))?.Value ?? generatorWrapped.Value;
}
public ThingTwo CachedThingTwo
{
get
{
return CacheGetWithGenerate(
MemoryCache.Default,
"Services.ThingTwoData",
() => GetThingTwo(), // ok, GetThingTwo isn't async this time, fudged example
DateTime.Now.Add(TimeSpan.FromMinutes(1)));
}
}
Do you know why MSDTC is being invoked?
PublicationOnly means that two connections can be created and one thrown away. I'm surprised you made this bug because you explicitly stated PublicationOnly (as opposed to the default safety mode which is safe). You explicitly allowed this bug.
For some reason I did not see that you tried ExecutionAndPublication already. Since not using it is a bug please fix the code in the question.
CreateConnection is also broken in the sense that in case of exception on open the connection object is not getting disposed. Probably harmless but you never know.
Also, audit this code for thread aborts which can happen when ASP.NET times out a request. You are doing very dangerous and brittle things here.
The pattern that I use is to use an IOC container to inject a connection that is shared for the entire request. The first client for that connection opens it. The request end event closes it. Simple, and does away with all that nasty shared, mutable, multi-threaded state.
Why are you using a cache for data that you do not want to lose? This is probably the bug. Don't do that.
What is ?.Value ?? generatorWrapped.Value about? The dictionary can never return null. Delete that code. If it could return null then forcing the lazy value would create a second connection so that's a logic bug as well.
I am using AdomdConnection connection class to connect to the Cube. I am using following code.
using (var conn = new AdomdConnection(ConnString))
{
conn.Open();
var cube = conn.Cubes[name];
//Do something
conn.Close();
}
AdomdConnection.ConnectionTimeout Property does not have setter property.
The default value for connectionTimeOut property is 0, which sets the time to infinite.
I have two questions:
Is there any way to set the timeout property for AdomdConnection?
When the cube is busy and your try to run the program, after creating the connection when you open the connection (conn.open()), system does not come out of this statement & never executes the next line of code. In such cases the application becomes irresponsible and there is no exception thrown. How can I inform user about such scenarios & make a log entry.
I looked into this similar tread but did not found it useful.
Thank you
The documentation states this for AdomdConnection.ConnectionTimeout
Gets the time to wait for a connection to be established before the
AdomdConnection stops trying to connect and generates an error.
So that means the timeout just talking to the server.
If you want a timeout when your running an actual command use the AdomdCommand.CommandTimeout property.
Gets or sets the time to wait for a command to run before the
AdomdCommand stops trying to run the command and generates an error.
Both can be set with the connection string.
http://msdn.microsoft.com/en-us/library/microsoft.analysisservices.adomdclient.adomdconnection.connectionstring.aspx
I am developing a .NET web application with C# and SQL Server as database, being newbie for both technologies. I have a problem when I attempt to save a lot of information at the same time.
My code is simple:
SqlConnection cn = null;
try
{
using (TransactionScope scope = new TransactionScope())
{
using (cn = Util.getConnection())
{
cn.Open();
BusinessObject.saveObject1(param1, cn);
BusinessObject.saveObject2(param2, cn);
BusinessObject.saveObject3(param3, cn);
BusinessObject.saveObject4(param4, cn);
...
scope.Complete();
}
}
I always use the same connection object because if an error happens, I must revoke any change in my data and the same behaviour if the process is ok, is needed.
I don't mind it the process of saving takes a lot of time, in my application is perfectly normal because I have to save a lot of information.
The weirdness here is:
When I execute this function in the same local area network of the database, it perfectly works.
However, if I execute it from outside, such as, connected by a VPN and consequently with higher latency, I get an error with the message: "The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements."
I have tried to change the timeout of the database through the connection string in the web.config but it didn't resolve anything. Also, if after each executeNonQuery() statement I do a cn.Dispose(), I get an error in the next attempt to use the connection object.
Do I have to change the parameters of TransactionScope object? Is there another better way to do this?
Thanks in advanced.
This is due to a timeout error. The TransactionScope might decide to rollback the transaction in case of a timeout.
You need to increase the timeout value in the TransactionScope constructor. The default max. timeout is 10min.
Move scope.Complete(); outside the connection block (MSDN article).
Did you try setting the Timeout = 0 in your Util.getConnection() function ? A value of 0 indicates no limit. This will complete the job surely. By setting the Timeout = 0 will complete every long operation job.
I've got a project called DotRas on CodePlex that exposes a component called RasConnectionWatcher which uses the RasConnectionNotification Win32 API to receive notifications when connections on a machine change. One of my users recently brought to my attention that if the machine comes out of sleep mode, and attempts to redial the connection, the connection goes into a loop indicating the connection is already being dialed even though it isn't. This loop will not end until the application is restarted, even if done through a synchronous call which all values on the structs are unique for that specific call, and none of it is retained once the call completes.
I've done as much as I can to fix the problem, but I fear the problem is something I've done with the RasConnectionNotification API and using ThreadPool.RegisterWaitForSingleObject which might be blocking something else in Windows.
The below method is used to register 1 of the 4 change types the API supports, and the handle to associate with it to monitor. During runtime, the below method would be called 4 times during initialization to register all 4 change types.
private void Register(NativeMethods.RASCN changeType, RasHandle handle)
{
AutoResetEvent waitObject = new AutoResetEvent(false);
int ret = SafeNativeMethods.Instance.RegisterConnectionNotification(handle, waitObject.SafeWaitHandle, changeType);
if (ret == NativeMethods.SUCCESS)
{
RasConnectionWatcherStateObject stateObject = new RasConnectionWatcherStateObject(changeType);
stateObject.WaitObject = waitObject;
stateObject.WaitHandle = ThreadPool.RegisterWaitForSingleObject(waitObject, new WaitOrTimerCallback(this.ConnectionStateChanged), stateObject, Timeout.Infinite, false);
this._stateObjects.Add(stateObject);
}
}
The event passed into the API gets signaled when Windows detects a change in the connections on the machine. The callback used just takes the change type registered from the state object and then processes it to determine exactly what changed.
private void ConnectionStateChanged(object obj, bool timedOut)
{
lock (this.lockObject)
{
if (this.EnableRaisingEvents)
{
try
{
// Retrieve the active connections to compare against the last state that was checked.
ReadOnlyCollection<RasConnection> connections = RasConnection.GetActiveConnections();
RasConnection connection = null;
switch (((RasConnectionWatcherStateObject)obj).ChangeType)
{
case NativeMethods.RASCN.Disconnection:
connection = FindEntry(this._lastState, connections);
if (connection != null)
{
this.OnDisconnected(new RasConnectionEventArgs(connection));
}
if (this.Handle != null)
{
// The handle that was being monitored has been disconnected.
this.Handle = null;
}
this._lastState = connections;
break;
}
}
catch (Exception ex)
{
this.OnError(new System.IO.ErrorEventArgs(ex));
}
}
}
}
}
Everything works perfectly, other than when the machine comes out of sleep. Now the strange thing is when this happens, if a MessageBox is displayed (even for 1 ms and closed by using SendMessage) it will work. I can only imagine something I've done is blocking something else in Windows so that it can't continue processing while the event is being processed by the component.
I've stripped down a lot of the code here, the full source can be found at:
http://dotras.codeplex.com/SourceControl/changeset/view/68525#1344960
I've come for help from people much smarter than myself, I'm outside of my comfort zone trying to fix this problem, any assistance would be greatly appreciated!
Thanks! - Jeff
After a lot of effort, I tracked down the problem. Thankfully it wasn't a blocking issue in Windows.
For those curious, basically once the machine came out of sleep the developer was attempting to immediately dial a connection (via the Disconnected event). Since the network interfaces hadn't finished initializing, an error was returned and the connection handle was not being closed. Any attempts to close the connection would throw an error indicating the connection was already closed, even though it wasn't. Since the handle was left open, any subsequent attempts to dial the connection would cause an actual error.
I just had to make an adjustment in the HangUp code to hide the error thrown when a connection is closed that has already been closed.
We're using TIBCO EMS from our ASP.NET 3.5 app for one interface to an external system, and it appears to be working just fine - except that the guys running the other side tells us we're racking up connections like crazy and never closing them....
What I'm doing is routing all TIBCO traffic through a single class with static member variables for both the TIBCO ConnectionFactory and the Connection itself, having been told that constructing them is pretty resource- and time-intensive:
private static ConnectionFactory Factory
{
get
{
if (HttpContext.Current.Application["EMSConnectionFactory"] == null)
{
ConnectionFactory connectionFactory = CreateTibcoFactory();
HttpContext.Current.Application["EMSConnectionFactory"] = connectionFactory;
}
return HttpContext.Current.Application["EMSConnectionFactory"] as ConnectionFactory;
}
}
private static Connection EMSConnection
{
get
{
if (HttpContext.Current.Application["EMSConnection"] == null)
{
Connection connection = Factory.CreateConnection(*username*, *password*);
connection.ExceptionHandler += new EMSExceptionHandler(TibcoConnectionExceptionHandler);
connection.Start();
HttpContext.Current.Application["EMSConnection"] = connection;
}
return HttpContext.Current.Application["EMSConnection"] as Connection;
}
}
Now my trouble is: where and how could I
tell the TIBCO connection to "auto-close" when no longer needed (like with the SqlConnection)
close the TIBCO connection on an error
close the TIBCO connection before our ASP.NET app finishes (or the user logs off)
I don't really seem to find much useful information on how to use TIBCO EMS from the C# / .NET world...... any takers?? Thanks!!
Firstly, I don't understand how you could be running out of connections. Since you're storing the connection in the application, you should only have a single connection for the entire IIS application.
That put aside, I would do the following:
When the connection is retrieved, create the connection as you do now;
After you've created the connection, spin up a background thread;
Set a DateTime to DateTime.Now;
Let the background check (e.g. every second or every 10 seconds) what the difference is between the date you've set and DateTime.Now. If that's longer than a specific timeout, kill the connection and set Application["EMSConnectionFactory"] to null;
When the background thread kills the connection, close the background thread;
Every time the connection gets requested, reset the DateTimetoDateTime.Now`.
This way, the connections should be closed automatically.
Note that you will have to introduce locking. You can use Application.Lock() and Application.Unlock() for this.
Concerning closing on an error: I see that you've attached an exception handler to the connection instance. Can't you close the connection with that?