I have an SQL database.
Then in one class I have an ExcelFunction:
[ExcelFunction(Description = "fonction de recherche")]
public static double id(string _isin)
{
double res;
res =DBSQL.Instance.getID(_isin);
return res;
}
Then in anoher class I have my connection and the creation of the singleton pattern (in order to be safe in case of multi-threading). The idea might not be clear, just ask me and I will try to explain. The point is to open a connection (using the singleton pattern), then do the request and then delete the singleton to close the connection.
Here is my code :
public class DBSQL : iAccesDB1
{
private SqlConnection MaConn = new SqlConnection("sefhgoefhouzeyf");
private static volatile DBSQL instance;
private static object syncRoot = new Object();
private DBSQL() {}
public static DBSQL Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new DBSQL();
}
}
return instance;
}
}
public void Connection()
{
MaConn.Open();
}
public void CloseConnection()
{
MaConn.Close();
}
public double getID(String _isin)
{
SqlDataReader rd;
double res = -9999;
SqlCommand cd = new SqlCommand("select cpn from tD where isin='" + _isin + "'", MaConn);
try
{
rd = cd.ExecuteReader();
if (rd.HasRows)
{
while (rd.Read())
res =double.Parse(rd["cpn"].ToString());
}
}
catch (Exception ex)
{
throw new Exception("1000: " + ex.Message);
}
return res;
}
}
The problem is that it does not work - in my excel cell I have the following: VALUE?
When your Excel-DNA function returns #VALUE to Excel, it probably means there was an unhandled exception.
I suggest you change your top-level function to return an 'object' which returns an error string if there is an exception, like this:
[ExcelFunction(Description = "fonction de recherche")]
public static object id(string _isin)
{
try
{
double res;
res = DBSQL.Instance.getID(_isin);
return res;
}
catch (Exception ex)
{
return "!!! ERROR: " + ex.ToString();
}
}
Related
I'm getting error: Connection must be valid and open when I start this program.
It works fine, but sometimes it happens
There is no problem with connection information and query syntax.
Please Help.
public class Connector : IDisposable
{
private MySqlConnection mySqlConnect;
public MySqlConnection MySqlConnect
{
get { return mySqlConnect; }
}
public Connector()
{
mySqlConnect = new MySqlConnection(DatabaseInformation.ConnStr);
Open();
}
private int Open() // Try Connect
{
try
{
if (mySqlConnect.State == ConnectionState.Closed)
mySqlConnect.Open();
return -1;
}
catch (MySqlException ex)
{
return ex.Number;
}
}
private int Close() // Try Disconnect
{
try
{
if (mySqlConnect.State == ConnectionState.Open)
mySqlConnect.Close();
return -1;
}
catch (MySqlException ex)
{
return ex.Number;
}
}
public void Dispose()
{
Close();
mySqlConnect.Dispose();
}
}
see this below code
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.local);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.remote);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.OrcsWeb);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.Sage);
Unity RegisterType not accepting enum but when if i pass string then no problem occur but i have to use enum. my full code as follow. so some one see my code and tell me what and where to fix in code as a result enum should be accepted.
full code
public enum ConType { local, remote, OrcsWeb, Sage, };
public interface IBBAConnection
{
IDbConnection GetConnection();
string ConType { get; set; }
}
public class BBAConnection : IBBAConnection
{
public ConType ConType { get; set; }
public IDbConnection GetConnection()
{
string _connectionString = "";
IDbConnection connection = null;
try
{
// inside if else logic we fetch connection string from ini file or from any source and inistialize connection.
if (ConType == ConType.local)
{
_connectionString = "put here local db connection";
connection = new System.Data.SqlClient.SqlConnection(_connectionString);
}
else if (ConType == ConType.remote)
{
_connectionString = "put here remote db connection";
connection = new System.Data.SqlClient.SqlConnection(_connectionString);
}
else if (ConType == ConType.OrcsWeb)
{
_connectionString = "put here website db connection";
connection = new System.Data.SqlClient.SqlConnection(_connectionString);
}
else if (ConType == ConType.Sage)
{
_connectionString = "put here sage connection";
connection = new System.Data.SqlClient.SqlConnection(_connectionString);
}
connection.Open();
}
catch (Exception ex)
{
string strErr = ex.Message;
}
return connection;
}
}
public static class Factory
{
static IUnityContainer cont = null;
public static IBBAConnection initialize(ConType oConType)
{
IBBAConnection oDbConnection = null;
cont = new UnityContainer();
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.local);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.remote);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.OrcsWeb);
cont.RegisterType<IBBAConnection, BBAConnection>(ConType.Sage);
oDbConnection = cont.Resolve<IBBAConnection>(oConType);
//oDbConnection.ConType = type;
return oDbConnection;
}
}
looking for guide line that what to change as a result Enum should be accepted.
Below is what I think you should do.
It will dramatically reduce the complexity of BBAConnection because you're letting your IConnectionConfig binding determine the connection string you need.
public interface IConnectionConfig
{
string GetConnectionString();
}
public class LocalConnectionConfig : IConnectionConfig
{
public string GetConnectionString()
{
return "db connection for local";
}
}
public class BBAConnection : IBBAConnection
{
private readonly IConnectionConfig config;
public BBAConnection(IConnectionConfig config)
{
this.config = config;
}
public IDbConnection GetConnection()
{
string _connectionString = "";
IDbConnection connection = null;
try
{
connection = new System.Data.SqlClient.SqlConnection(this.config.GetConnectionString());
connection.Open();
}
catch (Exception ex)
{
string strErr = ex.Message;
}
return connection;
}
}
The registrations:
container.RegisterType<IBBAConnection, BBAConnection>();
container.RegisterType<IConnectionConfig, LocalConnectionConfig>();
Conceptually Speaking
You would normally let your build configurations define what configs you are using. You can then use that in your code to define which config you need.
I'm not exactly sure how to address this issue. I have a mutex that is declared as such:
public class MyNamedLock
{
private Mutex mtx;
private string _strLkName;
public MyNamedLock(string strLockName)
{
_strLkName = strLockName;
//...
mtx = new Mutex(false, _strLkName, out bCreatedNew, mSec);
}
public bool enterLockWithTimeout(int nmsWait = 30 * 1000)
{
_nmsWaitLock = nmsWait;
//Wait
return mtx.WaitOne(nmsWait);
}
public void leaveLock()
{
_nmsWaitLock = 0;
//Release it
mtx.ReleaseMutex();
}
}
Then it is used in an ASP.NET page as such:
public class MyClass
{
private MyNamedLock gl;
public MyClass()
{
gl = new MyNamedLock("lock name");
}
public void funct()
{
try
{
//Enter lock
if (gl.enterLockWithTimeout())
{
//Do work
}
else
throw new Exception("Failed to enter lock");
}
finally
{
//Leave lock
gl.leaveLock();
}
}
}
This code doesn't give me any trouble in my dev environment but in the production it sometimes throws this exception:
Object synchronization method was called from an unsynchronized block
of code.
The description is kinda vague, but just doing the trace I found out that the exception is raised at the mtx.ReleaseMutex(); part. What does it mean and how to fix it?
You have some issues on your class, and on the way you use it.
You must release the mutex only if you have previous locked (and this is your error)
You need to Close and Dispose your opened mutex
Also is better to create it just before you going to use it and not when you create you class MyClass.
So I suggest at first look to change your class as:
public class MyNamedLock
{
private Mutex mtx = null;
private string _strLkName;
// to know if finally we get lock
bool cNeedToBeRelease = false;
public MyNamedLock(string strLockName)
{
_strLkName = strLockName;
//...
mtx = new Mutex(false, _strLkName, out bCreatedNew, mSec);
}
public bool enterLockWithTimeout(int nmsWait = 30 * 1000)
{
_nmsWaitLock = nmsWait;
bool cLock = false;
try
{
cLock = mtx.WaitOne(nmsWait, false);
cNeedToBeRelease = cLock;
}
catch (AbandonedMutexException)
{
// http://stackoverflow.com/questions/654166/wanted-cross-process-synch-that-doesnt-suffer-from-abandonedmutexexception
// http://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception.aspx
cNeedToBeRelease = true;
}
catch (Exception x)
{
// log the error
Debug.Fail("Check the reason of fail:" + x.ToString());
}
return cLock;
}
public void leaveLock()
{
_nmsWaitLock = 0;
if (mtx != null)
{
if (cNeedToBeRelease)
{
try
{
mtx.ReleaseMutex();
cNeedToBeRelease = false;
}
catch (Exception x)
{
Debug.Fail("Check the reason of fail:" + x.ToString());
}
}
mtx.Close();
mtx.Dispose();
mtx = null;
}
}
}
This the way you must call that class:
public class MyClass
{
public MyClass()
{
}
public void funct()
{
var gl = new MyNamedLock("lock name");
try
{
//Enter lock
if (gl.enterLockWithTimeout())
{
//Do work
}
else
throw new Exception("Failed to enter lock");
}
finally
{
//Leave lock
gl.leaveLock();
}
}
}
In your finally block you're releasing the mutex regardless of whether you actually acquired it in your try block.
In
try
{
//Enter lock
if (gl.enterLockWithTimeout())
{
//Do work
}
else throw new Exception("Failed to enter lock");
}
finally
{
//Leave lock
gl.leaveLock();
}
if gl.enterLockWithTimeout returns false, you will throw an exception but then try to release the lock in the finally block.
I have an established SQL Server database setup. I then generated an Entity Framework model in a Console Application to test some selecting, editing and adding to the database. All went well.
I am now moving more towards my final physical design of my WinForms and WebApp. So, I have decided to do the project in separate projects. I moved the Entity Framework to a Data project, I created a Services project, and I still have my console app as a test application (All in the same solution).
I have a ClassLib with data transfer objects to pass between my layers. So my GUI layer and Service layer don't know of the Entity Framework. I have helper methods in my EF project that convert the EF data into List etc...
Eg of a helper method:
using ClassLib;
namespace Data
{
public class PayeeDAL : EntityBase
{
public static List<PayeeDto> GetPayees()
{
var payees = (from payee in Db.payees
select payee).ToList();
List<PayeeDto> reply = new List<PayeeDto>();
foreach (var pa in payees)
{
PayeeDto p = new PayeeDto
{
PayeeId = pa.payee_id,
Name = pa.name,
Deleted = pa.deleted == null
};
reply.Add(p);
}
return reply;
}
}
}
And my data transfer object looks like this:
namespace ClassLib
{
public class PayeeDto
{
public int PayeeId { get; set; }
public string Name { get; set; }
public bool Deleted { get; set; }
}
}
So, my selection is working well with this design... but... have no idea how to handle saving.
In my console application, when the EF was available to me, I did this:
db.AddToaccount_transaction(ac);
account_transaction_line atl = new account_transaction_line
{
amount = amount,
cost_centre =
db.cost_centre.FirstOrDefault(
cc => cc.cost_centre_id == costcentreid),
sub_category =
db.sub_category.First(
sc => sc.sub_category_id == subcategoryId),
account_transaction = ac,
budget = db.budgets.FirstOrDefault(b => b.budget_id == budgetid)
};
db.AddToaccount_transaction_line(atl);
}
db.SaveChanges();
But now I don't have access to .AddTo.... and .SaveChanges... In my Console app, I'd create a parent object, and then add a few child objects... and then add the child objects to the parent object, and save.
But how would this be done in my new structure? I'm thinking I'd have a Save method in each of my helper classes... And then pass a List<> of the child objects, along with a single Parent class to the save method... and then transfor the Dtos to EF models, and then save it that way?
Is that an acceptable plan?
I only use DTO objects to transfer data from A to B. The updating, adding, removing etc., I always encapsulate in Commands (Command Pattern).
Retrieving data I do similarily with "Helper" classes.
Example of command pattern:
The base classes:
namespace Busker.Data.Commands
{
/// <summary>
/// The 'Command' abstract class
/// </summary>
public abstract class Command
{
private string message = "";
public string Message
{
get { return message; }
set { message = value; }
}
private bool success = false;
public bool Success
{
get { return success; }
set { success = value; }
}
private Validator validator = new Validator();
public Validator Validator
{
get { return validator; }
set { validator = value; }
}
private CommandStatusCode statusCode = CommandStatusCode.OK;
public CommandStatusCode StatusCode
{
get { return statusCode; }
set { statusCode = value; }
}
public LoggingLevel LoggingLevel = LoggingLevel.Debug;
//public BuskerContext BuskerContext;
public bool IsValid()
{
if (validator.Errors.Count > 0)
return false;
return true;
}
public abstract void Execute();
public void FailedSubCommand(Command cmd)
{
this.Success = cmd.Success;
this.Message = cmd.message;
}
}
}
namespace Busker.Data.Commands
{
public class Invoker
{
private Command command;
public Command Command
{
get { return command; }
set { command = value; }
}
public void SetCommand(Command command)
{
this.Command = command;
}
public virtual void ExecuteCommand()
{
if (command == null)
throw new Exception("You forgot to set the command!!");
try
{
log(this.command.GetType().Name + " starting execution ");
command.Execute();
if (!command.Success)
{
log(this.command.GetType().Name + " completed execution but failed. Message: " + command.Message + " " + command.StatusCode.ToString());
}
else
log(this.command.GetType().Name + " completed execution. Success!");
}
catch (Exception ex)
{
command.StatusCode = CommandStatusCode.Error;
Loggy.AddError("An unhandled error was caught in " + this.command.GetType().Name + ": " + ex.Message, ex);
command.Message = ex.ToString();
//throw;
}
}
private void log(string msg)
{
switch (command.LoggingLevel)
{
case Busker.Data.Constants.LoggingLevel.Debug:
Loggy.Debug(msg);
break;
case Busker.Data.Constants.LoggingLevel.Off:
break;
default:
Loggy.Add(msg);
break;
}
}
public virtual void ExecuteLinqCommand()
{
this.ExecuteCommand();
}
}
}
namespace Busker.Data.Commands
{
public static class Extensions
{
/// <summary>
/// Executes the command using the default invoker.
/// </summary>
/// <param name="aCommand"></param>
public static void Invoke(this Command aCommand)
{
System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace();
System.Reflection.MethodBase m = stackTrace.GetFrame(1).GetMethod();
String strMethodName = m.DeclaringType.Name + "." + m.Name;
try
{
Invoker invoker = new Invoker();
invoker.SetCommand(aCommand);
invoker.ExecuteCommand();
}
catch (Exception ex)
{
Loggy.AddError("An error occured in Extensions.Invoke. + " + strMethodName ,ex);
throw ex;
}
}
}
Implementation Example:
namespace Busker.Data.Commands.Message
{
public class CreateMessageCommand :Command
{
public CreateMessageCommand (int from, int to, string title, string body)
{
// set private variable..
}
public override void Execute()
{
// Do your stuff here
be.SaveChanges();
this.Success = true;
}
}
}
Usage:
CreateMessageCommand cmd = new CreateMessageCommand (...);
//Don't use the execute method of the command
//the invoker, because implemented as an extension can be exchange in different
//environments
cmd.Invoke();
I need to develop a single routine that will be fired each 5 minutes to check if a list of SQL Servers (10 to 12) are up and running.
Is there a way to simply "ping" a SQL Server from C# one with minimal code and sql operational requirements?
I have had a difficulty with the EF when the connection the server is stopped or paused, and I raised the same question. So for completeness to the above answers here is the code.
/// <summary>
/// Test that the server is connected
/// </summary>
/// <param name="connectionString">The connection string</param>
/// <returns>true if the connection is opened</returns>
private static bool IsServerConnected(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}
}
Execute SELECT 1 and check if ExecuteScalar returns 1.
See the following project on GitHub: https://github.com/ghuntley/csharp-mssql-connectivity-tester
try
{
Console.WriteLine("Connecting to: {0}", AppConfig.ConnectionString);
using (var connection = new SqlConnection(AppConfig.ConnectionString))
{
var query = "select 1";
Console.WriteLine("Executing: {0}", query);
var command = new SqlCommand(query, connection);
connection.Open();
Console.WriteLine("SQL Connection successful.");
command.ExecuteScalar();
Console.WriteLine("SQL Query execution successful.");
}
}
catch (Exception ex)
{
Console.WriteLine("Failure: {0}", ex.Message);
}
Wouldn't establishing a connection to the database do this for you? If the database isn't up you won't be able to establish a connection.
For what Joel Coehorn suggested, have you already tried the utility named tcping. I know this is something you are not doing programmatically. It is a standalone executable which allows you to ping every specified time interval. It is not in C# though. Also..I am not sure If this would work If the target machine has firewall..hmmm..
[I am kinda new to this site and mistakenly added this as a comment, now added this as an answer. Let me know If this can be done here as I have duplicate comments (as comment and as an answer) here. I can not delete comments here.]
Look for an open listener on port 1433 (the default port). If you get any response after creating a tcp connection there, the server's probably up.
You know, I first wrote this in 2010. Today, I'd just try to actually connect to the server.
public static class SqlConnectionExtension
{
#region Public Methods
public static bool ExIsOpen(
this SqlConnection connection, MessageString errorMsg = null)
{
if (connection == null) { return false; }
if (connection.State == ConnectionState.Open) { return true; }
try
{
connection.Open();
return true;
}
catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
return false;
}
public static bool ExIsReady(
this SqlConnection connction, MessageString errorMsg = null)
{
if (connction.ExIsOpen(errorMsg) == false) { return false; }
try
{
using (var command = new SqlCommand("select 1", connction))
{ return ((int)command.ExecuteScalar()) == 1; }
}
catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
return false;
}
#endregion Public Methods
}
public class MessageString : IDisposable
{
#region Protected Fields
protected StringBuilder _messageBuilder = new StringBuilder();
#endregion Protected Fields
#region Public Constructors
public MessageString()
{
}
public MessageString(int capacity)
{
_messageBuilder.Capacity = capacity;
}
public MessageString(string value)
{
_messageBuilder.Append(value);
}
#endregion Public Constructors
#region Public Properties
public int Length {
get { return _messageBuilder.Length; }
set { _messageBuilder.Length = value; }
}
public int MaxCapacity {
get { return _messageBuilder.MaxCapacity; }
}
#endregion Public Properties
#region Public Methods
public static implicit operator string(MessageString ms)
{
return ms.ToString();
}
public static MessageString operator +(MessageString ms1, MessageString ms2)
{
MessageString ms = new MessageString(ms1.Length + ms2.Length);
ms.Append(ms1.ToString());
ms.Append(ms2.ToString());
return ms;
}
public MessageString Append<T>(T value) where T : IConvertible
{
_messageBuilder.Append(value);
return this;
}
public MessageString Append(string value)
{
return Append<string>(value);
}
public MessageString Append(MessageString ms)
{
return Append(ms.ToString());
}
public MessageString AppendFormat(string format, params object[] args)
{
_messageBuilder.AppendFormat(CultureInfo.InvariantCulture, format, args);
return this;
}
public MessageString AppendLine()
{
_messageBuilder.AppendLine();
return this;
}
public MessageString AppendLine(string value)
{
_messageBuilder.AppendLine(value);
return this;
}
public MessageString AppendLine(MessageString ms)
{
_messageBuilder.AppendLine(ms.ToString());
return this;
}
public MessageString AppendLine<T>(T value) where T : IConvertible
{
Append<T>(value);
AppendLine();
return this;
}
public MessageString Clear()
{
_messageBuilder.Clear();
return this;
}
public void Dispose()
{
_messageBuilder.Clear();
_messageBuilder = null;
}
public int EnsureCapacity(int capacity)
{
return _messageBuilder.EnsureCapacity(capacity);
}
public bool Equals(MessageString ms)
{
return Equals(ms.ToString());
}
public bool Equals(StringBuilder sb)
{
return _messageBuilder.Equals(sb);
}
public bool Equals(string value)
{
return Equals(new StringBuilder(value));
}
public MessageString Insert<T>(int index, T value)
{
_messageBuilder.Insert(index, value);
return this;
}
public MessageString Remove(int startIndex, int length)
{
_messageBuilder.Remove(startIndex, length);
return this;
}
public MessageString Replace(char oldChar, char newChar)
{
_messageBuilder.Replace(oldChar, newChar);
return this;
}
public MessageString Replace(string oldValue, string newValue)
{
_messageBuilder.Replace(oldValue, newValue);
return this;
}
public MessageString Replace(char oldChar, char newChar, int startIndex, int count)
{
_messageBuilder.Replace(oldChar, newChar, startIndex, count);
return this;
}
public MessageString Replace(string oldValue, string newValue, int startIndex, int count)
{
_messageBuilder.Replace(oldValue, newValue, startIndex, count);
return this;
}
public override string ToString()
{
return _messageBuilder.ToString();
}
public string ToString(int startIndex, int length)
{
return _messageBuilder.ToString(startIndex, length);
}
#endregion Public Methods
}
Similar to the answer offered by Andrew, but I use:
Select GetDate() as CurrentDate
This allows me to see if the SQL Server and the client have any time zone difference issues, in the same action.
Here is my version based on the #peterincumbria answer:
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await dbContext.Database.CanConnectAsync(cToken);
I'm using Observable for polling health checking by interval and handling return value of the function.
try-catch is not needed here because:
I normally do this by open a connection but I had some cases where a simple test via Open caused a AccessViolationException
using (SqlConnection db = new SqlConnection(conn))
{
db.Open(); // -- Access Violation caused by invalid Server in Connection String
}
So I did a TCP check before the open like recommanded by Joel Coehoorn. C# Code for this may be:
string targetAddress = "";
try
{
targetAddress = GetServerFromConnectionString();
IPAddress ipAddress = Dns.GetHostEntry(targetAddress).AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 1433);
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(ipEndPoint);
}
}
catch (Exception ex)
{
LogError($"TestViaTcp to server {targetAddress} failed '{ex.GetType().Name}': {ex.Message}");
}