We have an Azure Scale Out resource, the problem is: For each instance, Hangfire launch a new server, any way to limit to one server only?
Assuming you are using Sql Server storage, which seems to be the case, you can do:
GlobalConfiguration.Configuration.UseSqlServerStorage("YourDB");
var servers = Hangfire.SqlServer.SqlServerStorage.Current
.GetMonitoringApi()
.Servers();
if (servers != null && servers.Count < 1)
//start new server here;
The workaround for this problem was: Check on SQLServer if there is an active Hangfire server:
using (var connection = new SqlConnection(myConnString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT MAX(LastHeartBeat) FROM HangFire.Server";
connection.Open();
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleResult))
{
if (reader.HasRows)
{
reader.Read();
DateTime lastBeat = reader.GetDateTime(0);
bool myResult = lastBeat >= DateTime.UtcNow.AddHours(-2);
}
}
}
Related
I am writing an SDK method with transaction using NpgsqlConnection for others to use.
When they were calling my method, they used SqlConnection with another transaction to wrap their DB stuff and my SDK's DB stuff.
If I set my SDK method without a transaction, the outer code was fine and my SDK method could be rolled back. (Which was odd too. Still figuring out why.)
If I set my SDK method with a transaction though, the outer code crashed with a TransactionAbortedException:
System.Transactions.TransactionAbortedException : The transaction has aborted.
---- Npgsql.PostgresException : 55000: prepared transactions are disabled
Currently we're using enlist=false at the SDK's connection string to prevent the inner transaction from joining the outer one but I'd like to know the reason behind this behavior.
Here's the code I'm reproducing the problem with:
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted,
},
TransactionScopeAsyncFlowOption.Enabled))
{
await using (var conn = new SqlConnection(#"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0"))
using (var cmd = new SqlCommand("insert into [Test].[dbo].[Test] (Id, \"Name\") values (1, 'A')", conn))
{
await conn.OpenAsync();
var result = await cmd.ExecuteNonQueryAsync();
await SdkMethodToDoStuffWithNpgsql(1);
scope.Complete();
}
}
I had SdkMethodToDoStuffWithNpgsql() to mock a method in a repository with Postgres context injected.
public async Task SdkMethodToDoStuffWithNpgsql(long id)
{
var sqlScript = #"UPDATE test SET is_removal = TRUE WHERE is_removal = FALSE AND id = #id;
INSERT INTO log(id, data) SELECT id, data FROM log WHERE id = #id";
using (var scope = new TransactionScope(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted,
},
TransactionScopeAsyncFlowOption.Enabled))
{
await using (var conn = new NpgsqlConnection(this._context.ConnectionString))
{
await conn.OpenAsync();
using (var cmd = new NpgsqlCommand(sqlScript, conn))
{
cmd.Parameters.Add(new NpgsqlParameter("id", NpgsqlDbType.Bigint) { Value = id });
await cmd.PrepareAsync();
var result = await cmd.ExecuteNonQueryAsync();
if (result != 2)
{
throw new InvalidOperationException("failed");
}
scope.Complete();
}
}
}
}
The above is the expected behavior - enlisting two connections in the same TransactionScope triggers a "distributed transaction"; this is known in PostgreSQL terminology as a "prepared transaction", and you must enable it in the configuration (this is the cause of the error you're seeing above). If the intention is to have two separate transactions (one for SQL Server, one for PostgreSQL) which commit separately, then opting out of enlisting is the right thing to do. You should also be able to use TransactopScopeOption.Suppress.
Note that distributed transactions aren't currently supported in .NET Core, only in .NET Framework (see this issue). So unless you're on .NET Framework, this won't work even if you enable prepared transactions in PostgreSQL.
i working with entity famework i need to transfer that code
RESTORE DATABASE [showing8-5-2013] FROM DISK = N'C:\Program Files (x86)\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\Backup\Company.bak' WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
to code Entity frame work
any help thanks
EF is a DB neutral provider concept. Such commands are by their nature DB specific. EF exposes a way to execute an SQL command:
MyContext.Database.ExecuteSqlCommand();
But you may as well just do it directly.
Pass your SQL command into a custom routine eg:
private static bool ExecuteSqlStatement(string connectionString, string statement) {
int rowsAffected;
using (var sqlConnection = new SqlConnection(connectionString)) {
using (var sqlCommand = new SqlCommand(statement, sqlConnection)) {
try {
sqlConnection.Open();
rowsAffected = sqlCommand.ExecuteNonQuery();
}
catch (Exception ex) {
// your handler or re-throw....
return false;
}
}
}
return rowsAffected == -1;
// see http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx
}
My ASP.NET C# application is connection to an Oracle database, running a stored procedure, and returning a reader with the command behavior of CloseConnection. The reader itself is disposed but - the Oracle sessions persist as inactive in V$SESSION. In a few hours, this turns into an error when another customer uses the application and we receive the error 'ORA-02399: exceeded maximum connect time, you are being logged off'. Further attempts to connect to Oracle return 'ORA-01012: not logged on'
Here is the connection string:
User Id=UserID;Password=userPass;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP) (HOST=IP.IP.IP.IP)(PORT=XXXX))(CONNECT_DATA=(SID=SID)));;Max Pool Size=5;Connection Timeout=60;Connection Lifetime=120;
Here is how the reader is used:
using (OracleDataReader dr = OraFunctions.ExecuteReader(input.ConnectionString,
CommandType.Text,
input.SqlStmt,
null))
{
while (dr.Read())
{
//do stuff here
}
dr.Dispose();
}
Here is the class that connects to Oracle:
public static OracleDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, OracleParameter[] commandParameters) {
OracleConnection connection = null;
OracleCommand command = new OracleCommand();
try {
connection = new OracleConnection(connectionString);
connection.Open();
command.Connection = connection;
command.CommandType = commandType;
command.CommandText = commandText;
if (commandParameters != null) {
foreach (OracleParameter param in commandParameters) {
command.Parameters.Add(param);
}
}
//Passing CommandBehavior.CloseConnection flag to the ExecuteReader method makes the DataReader connection to be closed when the DataReader is closed.
OracleDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
command.Dispose();
return reader;
} catch {
if (connection != null) {
command.Dispose();
connection.Close();
}
throw;
}
}
I'm looking for any hints on why the connections aren't actually closing. I'm using Oracle.DataAccess.Client. My guess is that the datareader's command behavior isn't working and that I need to recode this as a dataset where I can explitictly close the connection without having to rely on the CommandBehavior.
Thoughts? Thanks!
since you have connection.Open();
why didn't proper close it?
We never could get this worked out. We ended up disabling connection pooling and the open/inactive sessions went away in Oracle. If anyone reads this and has a suggestion on what was going wrong, I would definitely appreciate your input.
The possible solution I'm evaluating right now is to set Connection Lifetime parameter below the server's value.
The idea is when connection returned to the pool after performing query, it's lifetime is checked, and connection is closed if both conditions are met:
Connection's lifetime exceeded Connection Lifetime parameter value
Number of connections opened would not be lower than Min Pool Size parameter value
Kudos to Joao Morais for ODP.NET pooling details.
I am trying to connect to a database on an sql server in asp .net.
Here is a part of the code:
try
{
connection = new SqlConnection();
if(connection != null)
try
{
connection.ConnectionString = "Data Source=127.0.0.1,3306;Initial Catalog=MyPlace;User ID=root;Password=student";
connection.Open();
cmd = new SqlCommand(sqlQuery, connection);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
String s1 = (String)rdr["id"];
Response.Redirect(s1);
// Operate on fetched data
}
}
catch (Exception exc) { Response.Output.Write(exc.Message); }
}
catch(Exception ex)
{
Response.Output.Write(ex.Message);
}
finally
{
if (cmd != null)
cmd.Dispose();
if (connection != null)
connection.Close();
if (rdr != null)
rdr.Dispose();
}
The error I receive is :
A connection was successfully established with the server, but then an error occurred during the login process. (provider:TCP Provider, error:0 - An existing connection was forcibly closed by the remote host)
Any ideas why this might happen? I've already gone through the basic troubleshooting steps, but nothing seems to help...
Could be a number of things but start with the simplest which would be to verify that your MySql database is allowing connections. yes it seems silly, but we recently ran in to a case where an application wasn't behaving and part of the problem was the way the MySql users were configured which limited where they could connect from and what they could do once connected.
Assuming you can connect locally through the sql tools, and since you are running on the default port try this connect string instead of the one you are using
Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword;
Also make sure there aren't any conflicts with the MySql connectors on your box.
How do I set the command timeout property using Massive ORM?
Massive uses the System.Data.SqlClient to connect to SQL Server directly.
In order to change timeouts you have to look into that documentation.
I modified the original CreateCommand
All I did was add result.CommandTimeout on the second line
DbCommand CreateCommand(string sql, DbConnection conn, params object[] args)
{
var result = _factory.CreateCommand();
result.CommandTimeout = 45;
result.Connection = conn;
result.CommandText = sql;
if (args.Length > 0)
result.AddParams(args);
return result;
}
default is 30 seconds...
similar thing can be done in OpenConnection with ConnectionTimeout