I have a .Net application that is creating a new database. The current code is working great in development environment and in many production environments. So I am confident the code is fine.
However, we have a specific instance where the user is getting a timeout while the application is running the following SQL Command:
CREATE DATABASE NameOfDatabase
The code is pretty simple, and as you can see it uses the default timeout period for SQL commands which is 30 seconds:
using (SqlConnection connection = new SqlConnection(connectionString))
{
string query = "CREATE DATABASE " + databaseName;
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
command.ExecuteNonQuery();
}
Note: our log file shows the error occurs on ExecuteNonQuery which suggests that this is NOT a timeout while opening the connection, and rather during query execution.
The specific .Net error is:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
With a line from the stack trace to show my reasoning on it being a command timeout (not a connection timeout):
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
Note: This error information is obtained using a try/catch around the code which was left out of the question for simplicity as it is not relevant to the problem.
Questions
Under any reasonable (or even uncommon) situations, should a CREATE DATABASE query take this long to run and still be successful?
If it shouldn't take that long, what are the common causes for a timeout? (where should I be looking to debug the problem?)
I do not have enough rep points to comment. To get the specific error wrap command.ExecuteNonQuery(); in a try catch. at least you can get the specific error that is occurring. Also use using with SqlCommand that will dispose that object. Connection State
using (SqlConnection connection = new SqlConnection(connectionString))
{
string query = "CREATE DATABASE " + databaseName;
using(SqlCommand command = new SqlCommand(query, connection))
{
try
{
connection.Open();
if (connection.State == ConnectionState.Open)
command.ExecuteNonQuery();
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
Maybe this TechNet article can help? Troubleshooting: Timeout Expired
Related
I am working on dotnet core 3.1. I am working on API call.
When I call the API, below function in Repository will execute first by saving the data:
then another function will get execute by getting all saved data
Result of this API call I have got below:
However using statement will prevent these kind of issues but even If I used using statement though I have getting these issues.
wrap in sql connection. this is example
using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["connectionString"]))
{
conn.Open();
using (SqlCommand cmd1 = new SqlCommand($"truncate table tablename", conn))
{
dr = cmd1.ExecuteReader();
}
dr.Close();
}
I have a problem using SqlTransaction. Here's the code
SqlConnection conn = new SqlConnection(connectionString);
// assume that at this point I add try/catch and the connection is successfully opened.
conn.Open();
SqlTransaction trans = conn.BeginTransaction(IsolationLevel.RepeatableRead);
//.........
// Here I do my action with database, change it, commit, call ExecuteNonQuery, //ExecuteScalar,etc...
// And after that long processing with this transaction, I don't know why trans.Connection //is null. and therefore when I call trans.commit(), an exception was raised?
trans.commit();
Does anybody have any clues?
I assume this might be because of memory of database server was ate up because of too much connections. But I'm not sure.
How can I resolve this?
make use of using
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine("State: {0}", connection.State);
}
Seems like typo
con.BeginTransaction(IsolationLevel.RepeatableRead)
should be
conn.BeginTransaction(IsolationLevel.RepeatableRead)
use a using statement:
using (SqlConnection connection = new SqlConnection(connectionString))
{
//your code here
}
c# - SqlTransaction after catch transaction connection is null - Stack Overflow
SqlTransaction after catch transaction connection is null
Edyn said that:
Ran into a similar issue. In my case it was happening for a specific SqlException. Most exceptions would be caught and handled just fine, but whenever I got a conversion error (such as trying to convert a string to a number) it would automatically end the transaction.
In my solution, I rebuild the transacton if found the underlying connection is null. But it's a dirty work.
I have a C# Console Application that is essentially a long batch process that processes data on a nightly basis across many different databases. What is the proper or preferred way to test basic database connectivity at the beginning of this type of program? I ran into the issue of having an expired database password for one of my connections that was caught by exception handling but I want to test for basic connectivity at the very beginning.
Would a simple SELECT query suffice or is there a more efficient way of doing this for numerous databases?
IMHO the simplest way is trying to connect to database and, if you have a failure, you give up.
As you're running a night batch, it's not important to understand immediately the reason and solve it.
So something like this
using(SqlConnection conn = new SqlConnection(connectionString))
{
try
{
conn.Open();
// Do what you please here
}
catch (Exception ex)
{
// Write error to file
File.Append(...,
DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + " " +
ex.Message);
}
finally
{
conn.Close();
}
}
Next morning you can check file for errors...
'Connection.open`
is the simple way to determine if you can connect to db or not.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
}
If you get a SqlException with number 18487 or 18488 it indicates the password has been changed.
Connection.changePassword
You don't need to run any query.
If you use SqlConnection passing the connection string, you can just try to Open() the connection and you'll get an exception if you cannot connect
Something like:
try
{
var cnn = new SqlConnection(connectionString);
cnn.Open();
}
catch
{
// connection failed, do something
}
Opening (and then closing) a connection should be sufficient to test the password. however, this does not tell you , if a db-user has permissions to access specific tables.
Basically it's a patching mechanism
Here is what I'm doing :
Open a SQL connection.
Begin the transaction.
Update a record in database for the version of the software.
Execute some more queries on same database by using same connection.
Download a 15 to 20 MB file.
Execute a select query by using the same connection.
Commit the transaction.
Close the transaction.
This sequence is causing the problem of SQL Connection timeout as it takes time to download the file.
The problem is that I can commit the transaction only after downloading the file and not before that.
Writting the code in C#. Database used is SQLCE
Here is some part of the code:
SqlCeConnection conn = new SqlCeConnection("ConnectionString");
conn.Open();
SqlCeTransaction ts = conn.BeginTransaction();
//A method call executes all the methods that with parameters
(string sqlQuery, ref SqlCeConnection conn, SqlCeTransaction ts)
{
SqlCeCommand cmd = new SqlCeCommand();
cmd.Connection = conn;
cmd.Transaction = ts;
cmd.CommandText = sqlQuery;
cmd.ExecuteNonQuery();
}
//A method call downloads the file of 15 to 20 MB
//A method executes a select query that returns the version of the software by using same SQL connection.
//The above query gives the error of SQl connection timeout
ts.Commit();
conn.Close();
Can any one help me to solve the problem
Set you command timeout manually.
cmd.CommandTimeout = 180;
This example sets the Timeout to 180 seconds (3 minutes)
This is what I did.
I passed the same connection and transaction object to the method which was downloading the file.
In that method I executed a simple select query in the loop where the file was getting downloaded. This helped to keep the connection and transaction active.
Here even if your internet connection speed is slow it does not affect as in each loop your SQl query gets fired and keep the connection active.
I am using different SQL procedures in an application.
First procedures insert some rows then some processing in C#code and then 2nd procedure
do some updation then again some code processing then third procedure delete some record and then insert new record. When all is done on Sever 1 then data is fetch from this server and sent to Server 2 there record is deleted and new record is inserted.
IF there is error at any stage on any server in any procedure i want to roll back all the record.
I can not use begin trans because processing takes time and can not block table as others users are also using same tables in parallel. So kindly tell me how can i achieve it without blocking the table for other users.
Thanks in advance.
Edited (Added code example):
I tried Transaction Scope but i am getting exception while opening the connection. I configured MS DTC but may be not configured properly.
"
Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool."
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
try
{
dl.SetBookReadyToLive(13570, false);
//SetBookReadyToLive
dl.AddTestSubmiitedTitleID(23402);
dl.AddBookAuthorAtLIve(13570, 1);
ts.Complete();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
public void SetBookReadyToLive(long BookID, bool status)
{
try
{
if (dbConMeta.State != ConnectionState.Open)
dbConMeta.Open();
SqlCommand cmd = new SqlCommand("spSetBookReadyToLive", dbConMeta);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.Add("#BookID", BookID);
cmd.Parameters.Add("#status", status);
cmd.ExecuteNonQuery();
if (dbConMeta.State == ConnectionState.Open)
dbConMeta.Close();
}
catch
{
if (dbConMeta.State == ConnectionState.Open)
dbConMeta.Close();
}
}
I get the exception on opening the connection of method>
I am using SQL Server 2000, i have set the configuration of MS DTC on the machine where SQL Server is installed and also on my PC from where i am running the code. But still same exception.
Kindly help me to configure it
You can use the TransactionScope class. It works generally well but in case of distributed SQL servers like in your case requires the MS DTC enabled in both servers and configured properly (security has to be granted for execution of network transactions, distributed ones and so on...)
here a copy paste from an example on MSDN, you could "almost" use it like this... :)
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
source: TransactionScope Class
to minimize locks you could specify the IsolationLevel with the overload of the constructor which takes a TransactionScopeOptions, default is Serializable if you are fine with that you could set it to ReadCommitted.
Note: Personally I would not use this one unless absolutely needed, because it's a bit of a pain to have the DTC always configured and Distributed Transactions are in general slower than local ones but really depends on your BL / DAL logic.
Short answer : The same way you would do it if you would do it in MS SQL Management Studio.
You open a connection to a server.
Open a transaction for a specific server
You run your queries related to this server
You make sure to keep your connection alive while you... [go back to 1. for next server]
If all your queries worked, commit all your changes.
Else, rollback all your queries.
Warning : The first table will most likely be locked until you're done with all your servers/queries. What you could do here to help this : If you got a lot of data, you can transfer the data to temporary tables on every servers before doing the step #2. Once this is done, you open the transaction, do your fast things, then commit/rollback asap.
Note: I know you asked how to achieve this without locking the tables, hence why I added an idea in the « warning » part.