I have an app that connects to a MYSQL database through the entity framework. It works 100% perfectly, but I would like to add a small piece of code that will test the connection to the database upon app startup.
I had the idea of simply running a tiny command to the database and catching any exceptions, however if there is a problem (eg App.Config missing or Database server down) the app takes a huge amount of time to run this code and then throw the exception (~1 min). I imagine this is due to connection timeouts etc but I have fiddled with such properties to no avail.
Would anyone be able to assist with any ideas as to where to go?
Are you just wanting to see if the DB connection is valid? If so take a look at the
using (DatabaseContext dbContext = new DatabaseContext())
{
dbContext.Database.Exists();
}
http://msdn.microsoft.com/en-us/library/gg696617(v=vs.103).aspx
and for checking if a server machine is up, DB server or web services server , try this:
public PingReply Send( string hostNameOrAddress )
http://msdn.microsoft.com/en-us/library/7hzczzed.aspx
The solution as #Danilo Breda pointed out is to call the DbContext.Database.Connection.Open()
It is tested with EF6.
My implementaion:
public static bool CheckConnection()
{
try
{
MyContext.Database.Connection.Open();
MyContext.Database.Connection.Close();
}
catch(SqlException)
{
return false;
}
return true;
}
In EntityFramework Core you can simply call: Database.CanConnect();.
(using EF Core 2.2.1)
Summary: Determines whether or not the database is available and can be connected to.
Note that being able to connect to the database does not mean that it is up-to-date with regard to schema creation, etc.
I use this code for my project:
private bool TestConnectionEF()
{
using (var db = new SistemaContext())
{
db.Database.Connection.Open();
if (db.Database.Connection.State == ConnectionState.Open)
{
Console.WriteLine(#"INFO: ConnectionString: " + db.Database.Connection.ConnectionString
+ "\n DataBase: " + db.Database.Connection.Database
+ "\n DataSource: " + db.Database.Connection.DataSource
+ "\n ServerVersion: " + db.Database.Connection.ServerVersion
+ "\n TimeOut: " + db.Database.Connection.ConnectionTimeout);
db.Database.Connection.Close();
return true;
}
return false;
}
}
I know this is an old question, but here is my answer for anyone looking for a newer implementation.
I was able to use CanConnect to check the status of the database:
_database.Database.CanConnect();
# Async too
await _database.Database.CanConnectAsync(_cancellationTokenSource.Token);
I hope this helps others as well. Cheers!
I used the answer from #Sandor and did an extension method to use with EntityFramework Core.
Here's the code:
using Microsoft.EntityFrameworkCore;
using System.Data.Common;
namespace TerminalInventory
{
public static class ExtensionMethods
{
public static bool TestConnection(this DbContext context)
{
DbConnection conn = context.Database.GetDbConnection();
try
{
conn.Open(); // Check the database connection
return true;
}
catch
{
return false;
}
}
}
}
Now you just have to call:
if (!context.TestConnection())
{
logger.LogInformation("No database connection. Check the connection string in settings.json. {0}", configuration["connectionString"]);
return;
}
I am using the following code for MS SQL connection. Maybe, it will be useful for MySQL too. You don’t even need to use an EF or EF Core.
public bool IsDbConnectionOK()
{
SqlConnectionStringBuilder conStr = new SqlConnectionStringBuilder
{
DataSource = ButtonServerName.Text, // <-- My Form Elements
InitialCatalog = ButtonDBName.Text, // <-- My Form Elements
UserID = EditUserName.Text, // <-- My Form Elements
Password = EditPassword.Text, // <-- My Form Elements
IntegratedSecurity = false,
ConnectTimeout = 30
};
string connectionstring = conStr.ToString();
try
{
using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionstring))
{
connection.Open();
return true;
}
}
catch (System.Data.SqlClient.SqlException ex)
{
MessageBox.Show(ex.Message + Environment.NewLine +
"Error line: " + ex.LineNumber + Environment.NewLine +
"Procedure name: " + ex.Procedure);
return false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
Related
I have the code in .NET CORE deployed on windows works fine when c# mongo db client access the document. However when the same code is deployed on linux machine takes 15 minutes to fetch the document and it happens intermittently. I also updated the MongoDb driver to 2.10.4 but it didn't work for me.
// Code trying to fetch Document from web api , calling library method to fetch document
MongoDbService _mongoDbClient = new MongoDbService(_configuration["MongoDBConnection"]);
Conversation storedmodel = new Conversation ();
for (int i = 0; i < 10; i++)
{
try
{
storedmodel = _mongoDbClient.GetDocumentFromConversationId(ConversationId);
break;
}
catch (Exception ex)
{
if (i == 9)
{
//Logging exception
LumenTelemetry.TrackEvent(conversationID, " Error - " + ex.Message + " " + ex.InnerException + " " + ex.StackTrace);
}
}
}
//////////////////////// Code in Library Project
public interface IMongoService
{
IMongoDatabase GetDatabase(string dbName);
Conversation GetDocumentFromConversationId(string conversationId);
}
public class MongoDbService : IMongoService
{
private readonly MongoClient _mongoClient;
public MongoDbService(string conStr)
{
var connection = new MongoDbConnection(conStr);
_mongoClient = connection.MongoConnection;
}
public Conversation GetDocumentFromConversationId(string conversationId)
{
IMongoDatabase db = _mongoClient.GetDatabase("ConversationDb");
var collection = db.GetCollection<Conversation>("ConversationCollection/documents");
var document = collection.Find(doc => doc.ConversationId == conversationId).FirstOrDefault();
return document;
}
}
Enable logging to troubleshoot:
command monitoring in the driver
look at server logs
Identify where the time is spent:
prior to anything mongodb-related happening? (problem in your application unrelated to mongodb)
server selection
query write/request
query processing on server
Play with server selection timeout, connect timeout, socket timeout & maxTimeMS to identify the cause.
My Singleton is throwing a StackOverflowException, but yesterday it worked fine and the unique change was the database in the Connection String. It is a console application and the debug is very complicated:
class OracleSingleton
{
private static OracleConnection instance;
private OracleSingleton() { }
public static OracleConnection Instance
{
get
{
if (instance == null)
{
try
{
instance = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);
}
catch (Exception ex)
{
LogHelper.WriteMessage("Error trying to create a new connection. - " + ex.Message.ToString() + " - " + ex.InnerException.ToString().Trim());
}
}
return instance;
}
}
}
My App.config:
<configuration>
<connectionStrings>
<add name="OracleConnection" connectionString="Password=somepassword;Persist Security Info=True;User ID=someuser;Data Source=DATABASE01"/>
</connectionStrings>
//Some stuff
</configuration>
Can you guys show me what is wrong and why yesterday it worked fine?
EDIT:
I use the Singleton to do a lot of things. I Know that the problem is in the singleton because my application shows the StackoverflowException without log anything, who is one of the places where I use the Singleton. Below, my LogHelper.WriteMessage method, who is called at the first line of program to say" Hi, the application is running right now ":
public static void WriteMessage(string info)
{
using (OracleConnection conn = OracleSingleton.Instance)
{
using (OracleCommand cmd = new OracleCommand("INSERT INTO TB_LOG (DT_LOG, ID_PERMISSAO, ID_USUARIO, NM_USUARIO, DS_LOG) VALUES (TO_CHAR (SYSDATE, 'MM-DD-YYYY HH24:MI:SS'), 5025, 5025, 'IMPORTADORCAIXA', '" + info + "')", conn))
{
try
{
conn.Open();
cmd.ExecuteNonQuery();
} catch (Exception ex)
{
Console.WriteLine(DateTime.Now + " - Erro ao conectar com o banco. por favor, verifique o erro: " + ex.Message.ToString() + ", " + cmd.CommandText.ToString());
}
}
}
new LogHelper();
eventLog.WriteEntry(info);
Console.WriteLine(DateTime.Now + " - " + info);
}
Your "singleton" is indeed recursive on some paths. What happens if this line
instance = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);
throws exception, for example if connection string is invalid? You log that exception with WriteLog which again references singleton with
using (OracleConnection conn = OracleSingleton.Instance)
So if connection string is invalid, or connection creation constantly fails for other reason - you go into recursion and eventually end with StackOverflowException when stack space is exhausted.
By the way, with
using (OracleConnection conn = OracleSingleton.Instance)
you also dispose your connection, making it unusable for subsequent invocations.
Best way to resolve it is to just get rid of singleton, there is no need for it. It's bad practice to have global connection - just create it every time you need it and dispose (close) when you are done with it. Connection pool will manage the rest for you.
If you don't want to do serious refactoring for some reason, at least change to something like this:
public static OracleConnection Create() {
// no need to catch any exceptions here
return new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnection"].ConnectionString);
}
And use as you already do:
using (OracleConnection conn = OracleSingleton.Create())
Currently I am doing an assignment in which I need to visit database of n number of servers to fetch some results.I have achieved this by iterating through the list of servers and raising tasks each one for each server in the collection. The task calls a function which basically makes an connection with the database,run query and disconnect from database.
My question is I am doing right by making a new connection on each polling with the database and closing it everytime or is this would be the best approach to keep a db connection open and fetch the result and then keep it open on next polling iteration.
PollingServerTimer() is being called by timer everytime.My polling timer is 3 sec.
Something like this :
private void PollingServerTimer(object sender, ElapsedEventArgs e)
{
foreach (var item in ServerOperationCollHandler)
{
if (item.RebootStatus != true)
{
PushItemIntoQueue(item);
}
}
}
public void PollingServerQueue()
{
while (isRunning)
{
this.waitHandle.WaitOne();
lock (syncRoot)
{
if (ServerQueue.Count > 0)
{
ServerOperationDataModel obj;
try
{
ServerQueue.TryDequeue(out obj);
Task GetCountFromDbTask = new Task(() => GetCountFromDb(obj));
GetCountFromDbTask.Start();
this.waitHandle.Reset();
}
catch (Exception ex)
{
MessageBox.Show("Problem encountered while finding iterim and recovery count");
isRunning = false;
break;
}
}
}
}
}
public void GetCountFromDb(ServerOperationDataModel obj)
{
ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;
DataBaseHandler dbHandler = new DataBaseHandler(serverObject.DataBaseIP, serverObject.DataBasePort, serverObject.DataBaseName, serverObject.DataUserName, serverObject.DataUserPassword);
int attempts = 0;
do
{
try
{
dbHandler.connect();
}
catch (Exception ex)
{
break;
serverObject.DataBaseConnectionStatus = false;
log.Error("Connection attempt " + attempts + " failed.Retrying connection. Exception details :" + ex.ToString());
attempts++;
}
} while (attempts < _connectiontRetryAttempts && !dbHandler.isConnected());
if (dbHandler.isConnected())
{
/*Fetch Result and then get disconnect*/
dbHandler.disConnect();
}
else
{
//string msgLog = "Server : " + obj.ServerComponentIdentifier + " | " + obj.IPstring + "Connection cannot be established with the DB: " + obj.DataBaseIP + " | "+ obj.DataBasePort + " | " + obj.DataBaseName + " after a series of retries";
//LoggerUpdate.LogMessage(msgLog, LOGTYPE.POLLINGDATABASE, LoggerUpdate.ReturnLogDisplayObject(DateTime.Now, obj.ServerComponentIdentifier + "|" + obj.IPstring, Convert.ToInt16(LOGTYPE.POLLINGDATABASE), obj, msgLog));
}
}
I would not be concerned at all. Assuming you connect to the SQL Server (or a similar, enterprise DBMS), database connections are pooled at the client side which means that establishing the connection is costly only the first time the client connects to a particular db (formally: to a new, previously unseen connection string) and then each connection to the same database costs almost nothing.
If it hadn't been for pooling, applications servers would not be able to handle hundreds of concurrent browser connections that query the same data source. You would need much more than a connection every 3 seconds to cause any risk of depleting server or client resources.
You can read more on how pooling works
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling
A side note: You should polish your code a little bit.
For example, you have
GetCountFromDb(ServerOperationDataModel obj)
but then
ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;
Why would you need to cast the obj to another variable of the very same type?
In the catch clause, you have break and some code below it which looks unreachable.
Take a look at the .NET SqlDependency object. This allows you to register a query with a database and, using an OnChange handler, receive notification whenever the result of the query changes.
Is there any way to check DB instance is up or not. It is like health check monitoring. I need to connect to Database server using c# .net and should check the DB instance status and display the results.
Why not just try connecting to the DB and see if it's up or not like
public string GetDBStatus(string connectionString)
{
string status = string.Empty;
try
{
//connecting to your DB
status = "Up";
}
catch(Exception ex)
{
status = "Down";
//log error to somewhere
}
return status;
}
I need to learn how to use SMO within a C# program, so the first thing I did was start a new, console app and then began putting in the basics. I decided to make the app accept parameters so I can pass in things like usernames, logins, etc. As I work on it and build it I have a PowerShell window open where I can call the app, give it parameters or not, etc. But something weird is happening which I don't understand. Sometimes when I run the app in the PowerShell window, it's then deleted for some reason. Why is it doing that? I discovered it when it first gave me the following error message:
Program 'SmoListLogins.exe' failed to run: The system cannot find the file specifiedAt line:1 char:1 + .\SmoListLogins.exe "MYCOMPANY\Rod"
My SmoListLogins.exe program isn't there. Naturally I can easily re-create it, but I don't understand why its being deleted.
So you can see what I'm working with, here's the source code. I took it from a MSDN article and have added a little bit:
using System;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
namespace SmoListLogins
{
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
var userName = args[0];
ListLogins(userName);
}
else
{
ListLogins();
}
}
static private void ListLogins(string userName = "")
{
var userNamePassed = (userName != "");
Server srv = new Server("YOURSQLINSTANCE");
//Iterate through each database and display.
foreach (Database db in srv.Databases)
{
Console.WriteLine("========");
Console.WriteLine("Login Mappings for the database: " + db.Name);
Console.WriteLine(" ");
//Run the EnumLoginMappings method and return details of database user-login mappings to a DataTable object variable.
DataTable d;
try
{
d = db.EnumLoginMappings();
//Display the mapping information.
foreach (DataRow r in d.Rows)
{
var userNameMatches = false;
var starting = true;
foreach (DataColumn c in r.Table.Columns)
{
if (!userNamePassed)
{
Console.WriteLine(c.ColumnName + " = " + r[c]);
}
else
{
if (starting)
{
starting = false;
if (userName == r[c].ToString())
{
userNameMatches = true;
}
}
if (userNameMatches)
{
Console.WriteLine(c.ColumnName + " = " + r[c]);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error processing database: {db.Name}");
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine();
}
}
}
}
}
I believe I now know what was deleting my executable. It wasn't something I thought of, so I'm sharing with everyone the answer. Today I got an email from our chief security officer, informing me that the program I wrote was being blocked by Symantec Endpoint Protection. In my testing I'd run my app over and over again. After a few iterations of that it would disappear. It didn't occur to me that it was our corporate AV that might be doing it. Now it looks as though that is exactly what was going on.
Thank you everyone for your input in trying to help me resolve this. I hope that if anyone else encounters this problem they might consider the possibility of their AV as the reason why the app they wrote disappears.