How to close all existing connections to a DB programmatically - c#

I want to close the existing connections to an SQL Server so that I can do a restore on that database. I am using the entity framework. I tried executing
alter database YourDb
set single_user with rollback immediate
but then I get an exception saying that
Connection was not closed
I can not figure out why the connections are not allowed to close?
This image shows the full exception
this is the method,
public void dbQueueryExctr(string queuery)
{
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
connectionx.Open();
//connectionx.Open(); // Removed
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
reader = cmd.ExecuteReader();
connectionx.Close();
}
Edit:
I removed the first .Open(). Now I have only Open()

It does seem that Entity Framework keeps a connection to the database. You can see it be executing sp_who2 in SQL Server Management Studio where Entity Framework is listed as EntityFrameworkMUE under ProgramName.
You don't have to use "raw" sql statements to disconnect the active connections though, it can be solved this way as well:
Server server = new Server(".\\SQLEXPRESS");
Database database = new Database(server, dbName);
database.Refresh();
server.KillAllProcesses(dbName);
database.DatabaseOptions.UserAccess = DatabaseUserAccess.Single;
database.Alter(TerminationClause.RollbackTransactionsImmediately);
//restore.SqlRestore(server);

You get that error when you are call Open() on a connection twice. You should make all SqlConnection objects you create inside using blocks and only open them once.
If you are reusing connections "to make it faster" .NET already does that by default for you via Connection Pooling but you must dispose of the connection object to make it work.

You need to dispose the reader, the command and the connection. Your reader is not disposed. This code snippet will guarantee that the connection is closed even if there are exceptions thrown during the read process.
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "Command text.....";
using (var reader = cmd.ExecuteReader())
{
....
}
}
}

Your first problem (now that you have posted your code) is you call open twice:
public void dbQueueryExctr(string queuery)
{
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
//YOU CALL OPEN HERE
//DELETE THIS ONE!!!
connectionx.Open();
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
//AND OPEN HERE
connectionx.Open();
reader = cmd.ExecuteReader();
//You do not need connectionx.Close() here
//You have it within a using which will dispose the connection
//upon exiting the using scope.
connectionx.Close();
}
Next your problem will require you to reset the database to force close all connections. You will have to use a separate connection string to connect to MASTER not the database you are trying to close all connections to.
alter database <data base>
set offline with rollback immediate
alter database <data base>
set online with rollback immediate
Once you have executed the above SQL from MASTER against the database needing reset you should be good to do whatever you need to do. Remember, connect to master!! If you connect to the database you are trying to reset you end up closing all connections, including yourself, which will not work!
Change your Catalog to master.
Example Connection String (from MSDN):
"Persist Security Info=False;Integrated Security=true;Initial Catalog=Master;server=(local)"
Also ensure the SQL User you are using has full permissions to master. You do this by opening management studio and looking at the users collection under master.

The error is pretty clear...using Linq that way, you can't close the connection you are currently on. I haven't tried this but I think the following would work...try creating a stored procedure in your database and run it in your C# code using either a TableAdapter or SqlCommand(you can still use Linq too). Your code won't know you are about to run a stored procedure that is about to kill it's connection so it should work.
CREATE PROCEDURE [dbo].[sp_KillSpidsByDBName]
#dbname sysname = ''
AS
BEGIN
-- check the input database name
IF DATALENGTH(#dbname) = 0 OR LOWER(#dbname) = 'master' OR LOWER(#dbname) = 'msdb'
RETURN
DECLARE #sql VARCHAR(30)
DECLARE #rowCtr INT
DECLARE #killStmts TABLE (stmt VARCHAR(30))
-- find all the SPIDs for the requested db, and create KILL statements
-- for each of them in the #killStmts table variable
INSERT INTO #killStmts SELECT 'KILL ' + CONVERT (VARCHAR(25), spid)
FROM master..sysprocesses pr
INNER JOIN master..sysdatabases db
ON pr.dbid = db.dbid
WHERE db.name = #dbname
-- iterate through all the rows in #killStmts, executing each statement
SELECT #rowCtr = COUNT(1) FROM #killStmts
WHILE (#rowCtr > 0)
BEGIN
SELECT TOP(1) #sql = stmt FROM #killStmts
EXEC (#sql)
DELETE #killStmts WHERE stmt = #sql
SELECT #rowCtr = COUNT(1) FROM #killStmts
END
END
GO
Now you can run this stored procedure from code and it will kill open connections even your own. Enjoy!

It is good practice to check to see if the connection is open before attempting to open it. Try adding a check before trying to open your connection, something like this:
using (SqlConnection connectionx = new SqlConnection(CONNECTIONSTRING))
{
if(connectionx.State != ConnectionState.Open
connectionx.Open();
cmd.CommandText = queuery;
cmd.CommandType = CommandType.Text;
cmd.Connection = connectionx;
reader = cmd.ExecuteReader();
connectionx.Close();
}
This will help prevent the issue you described.

You can use SqlConnection.ClearAllPools and SqlConnection.ClearPool to close all or one connection in from .NET.
ClearPool clears the connection pool that is associated with the connection. If additional connections associated with connection are in use at the time of the call, they are marked appropriately and are discarded (instead of being returned to the pool) when Close is called on them.
ClearAllPools resets (or empties) the connection pool. If there are connections in use at the time of the call, they are marked appropriately and will be discarded (instead of being returned to the pool) when Close is called on them.
for examples:
using(var comm = new SqlConnection())
using(var comExecuteInsert = new SqlCommand())
{
comExecuteInsert.Connection = comm;
comExecuteInsert.CommandType = CommandType.StoredProcedure;
comExecuteInsert.CommandText = strProcedureName;
comExecuteInsert.ExecuteScalar();
comExecuteInsert.Parameters.Clear();
comm.Close();
}
SqlConnection.ClearAllPools();

Once exam this way, this is my Data access layer samples:
public T ExecuteScalar<T>(SqlCommand cmd, params SqlParameter[] Params)
{
try
{
if (Transaction != null && Transaction != default(SqlTransaction))
cmd.Transaction = Transaction;
else
cmd.Connection = SqlConn;
if (Params != null && Params.Length > 0)
{
foreach (var param in Params)
cmd.Parameters.Add(param);
}
Open();
var retVal = cmd.ExecuteScalar();
if (retVal is T)
return (T)retVal;
else if (retVal == DBNull.Value)
return default(T);
else
throw new Exception("Object returned was of the wrong type.");
}
finally
{
Close();
}
}

Related

Query not saving to database

I'm trying to save a note into the database by user input but my code isn't saving it to the Database.
I'm planning on checking the user input aswell with functions.
SqlConnection con = database.GetConnection();
SqlCommand command = new SqlCommand("INSERT INTO notities (notities_gebruiker, notities_datum, notities_doeldatum, notities_bericht) values(#notities_gebruiker, #notities_datum, #notities_doeldatum, #notities_bericht)", con);
command.Parameters.AddWithValue("#notities_gebruiker", this.gebruikerid.ToString());
command.Parameters.AddWithValue("#notities_datum", DateTime.Now);
command.Parameters.AddWithValue("#notities_doeldatum", DateTime.ParseExact(this.targetDate.Text, "dd/MM/yyyy", null));
command.Parameters.AddWithValue("#notities_bericht", this.Note.Text);
con.Open();
command.ExecuteNonQuery();
con.Close();
initialiseListBox();
What's happening is that whenever I close my application the database loses it's values saved and goes back to original state. I can add items manually though..
EDIT: It rolls back the rows I have added in via application but I am able to pull the data from the database I saved if I keep it running.
You're forgetting to commit the data you've just inserted. Use the SqlTransaction class to begin a transaction:
SqlTransaction myTransaction = con.BeginTransaction();
command.ExecuteNonQuery();
myTransaction.Commit();
It would be a good idea to make use of the Using statement to make sure your connection, command and transaction are disposed of once the code block has been complete, rather than manually calling Close() methods:
Using (SqlConnection con = database.GetConnection())
{
con.Open();
Using (SqlCommand command = new SqlCommand("sqlhere"))
{
Using (SqlTransaction myTransaction = con.BeginTransaction())
{
//your code here
}
}
}
SqlTransaction class:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction(v=vs.110).aspx
Neat article on using statements:
http://www.codeproject.com/Articles/6564/Understanding-the-using-statement-in-C
Look for a copy of your database containing the data in your bin/debug folder.
Best way to avoid this is to use a full path in your connection string and avoid |DataDirectory| while debugging

Inserting data into sql server fails with no reason

I'm quite used to using c# with SQL server. I have no idea why a simple statement would fail to insert data. My code is as follows:
query = "INSERT INTO MCDPhoneNumber ([MCDID],[PhoneNumber])" +
"VALUES("+maxid+", '"+tel+"')";
SqlConnection conn = new SqlConnection("Data Source=source; ...");
SqlCommand newCommand = new SqlCommand(query, conn);
int success= myCommand.ExecuteNonQuery();
if (success!= 1)
{
MessageBox.Show("It didn't insert anything:" + query);
}
First of all let me tell that I know that I should use parameters for data and I initially did, but when it failed I tried a simple query and it still fails. For addition I can tell that I have a similar insert just before that one in another table and it works. What's funnier is that when I copy paste query to SQL Server Management Studio it works. It also doesn't report any error in process.
====================== Edit ===============================
If you wish to use old command object (i.e. myCommand) then use following code instead of creating a new command(newCommand)
myCommand.CommandText = query;
myCommand.CommandType = System.Data.CommandType.Text;
And then execute it
you are binding query with newCommand and executing myCommand.
====================== Edit ===============================
SqlCommand newCommand = new SqlCommand(query, conn);
here you have defined newCommand for SQLCOMMAND object
int success= myCommand.ExecuteNonQuery();
and you are accessing it as myCommand
And moreover i think you are not opening connection
First of all, you define your command as newCommand but you executing your myCommand.
You should always use parameterized queries for your sql queries. This kind of string concatenations are open for SQL Injection attacks.
query = "INSERT INTO MCDPhoneNumber (MCDID, PhoneNumber) VALUES(#maxid, #tel)";
using(SqlConnection conn = new SqlConnection("Data Source=source; Initial Catalog=base; Integrated Security = true"))
{
SqlCommand newCommand = new SqlCommand(query, conn);
conn.Open();
newCommand.Parameters.AddWithValue("#maxid", maxid);
newCommand.Parameters.AddWithValue("#tel", tel);
int success= newCommand.ExecuteNonQuery();
if (success != 1)
{
MessageBox.Show("It didn't insert shit:" + query);
}
}
And please be more polite about your error messages :)

Sql connetion doesn't open in windows service

I have a simple windows service and within this service I'm trying to connect to a sql server in a timer block (I tried to do that only once in onStart method -> same result).
For the moment I'm trying just to execute a select, using the following code:
using (SqlConnection sc = new SqlConnection())
{
var sqlConnection = new SqlConnection(_sqlConnectionString);
string commanda = "SELECT Moneda, SimbolMoneda FROM NomMoneda WHERE Moneda != '' AND SimbolMoneda != ''";
SqlCommand command = new SqlCommand(commanda, sqlConnection);
command.CommandType = System.Data.CommandType.Text;
IDataReader reader;
sc.ConnectionString = _sqlConnectionString;
sc.Open();
reader = command.ExecuteReader(CommandBehavior.CloseConnection);
}
I attached the service to debug, and I noticed that it didn't pass by this line of code sc.Open().
The service is not on the same machine as the sql server, but I have tried to install it under different users, LocalSystem, NetworkService, user within the same domain with the sql server, but with no result.
Any help would be appreciated.
It looks like you may have a logical error in this code. You are using sc for the SqlConnection, but when you create the command object you use sqlConnection, which is never actually opened.
This line is the problem:
SqlCommand command = new SqlCommand(commanda, sqlConnection);
Try the following instead:
SqlCommand command = new SqlCommand(commanda, sc);
EDIT at 10:22 following user comment
Just to confirm that you have made the change as indicated, I've re-jigged your code. Could you try the following:
using (SqlConnection sc = new SqlConnection())
{
sc.ConnectionString = _sqlConnectionString;
sc.Open();
string commanda = "SELECT Moneda, SimbolMoneda FROM NomMoneda WHERE Moneda != '' AND SimbolMoneda != ''";
SqlCommand command = new SqlCommand(commanda, sc);
command.CommandType = System.Data.CommandType.Text;
IDataReader reader;
reader = command.ExecuteReader();
}
I would expect that whatever the issue is it would be easier to figure out if you had a logging mechanism in place to catch and log unhandled exceptions. Due to the fact that Windows Services do not have a user interface you should implement logging from the beginning. Otherwise you will get to a point where the service terminates unexpectedly and what little information you gather from the system logs won't be enough to help you.
In short, add file logging and you'll probably figure out the issue immediately.
The problem was simple, but hard to detect. My connection string wasn't prefixed with the # char:
ex: _connectionString = #"Data Source =.......";

Why does my application hang while trying to close a SqlConnection object?

I am trying to get column information in C# from a SQL table on SQL Server. I am following the example in this link: http://support.microsoft.com/kb/310107 My program strangely gets hung up when it tries to close the connection. If the connection is not closed, the program exits without any Exceptions. Here's my code:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
Putting the SqlConnection inside a using block also causes the application to hang unless CommandBehavior.KeyInfo is changed to CommandBehavior.SchemaOnly.
using (SqlConnection connection = new SqlConnection(#"MyConnectionString"))
{
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast even here in the using
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
}
The table in question has over 3 million rows, but since I am only obtaining the Schema information, I would think this wouldn't be an issue. My question is: Why does my application get stuck while trying to close a connection?
SOLUTION: Maybe this isn't optimal, but it does work; I inserted a command.Cancel(); statement right before Close is called on connection:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
command.Cancel(); // <-- This is it.
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
I saw something like this, long ago. For me, it was because I did something like:
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader();
// here, I started looping, reading one record at a time
// and after reading, say, 100 records, I'd break out of the loop
connection.Close(); // this would hang
The problem is that the command appears to want to complete. That is, go through the entire result set. And my result set had millions of records. It would finish ... eventually.
I solved the problem by adding a call to command.Cancel() before calling connection.Close().
See http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610 for more information.
It looks right to me overall and I think you need a little optimization. In addition to the above suggestion regarding avoiding DataReader, I will recommend to use connection pooling. You can get the details from here :
http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854
Could you try this?
DataTable dt = new DataTable();
using(SqlConnection conn = new SqlConnection("yourConnectionString"))
{
SqlCommand cmd = new SqlCommand("SET FMTONLY ON; " + yourQueryString + "; SET FMTONLY OFF;",conn);
conn.Open();
dt.Load(cmd.ExecuteReader());
}
SET FMTONLY ON/OFF from MSDN seems the way to go
There is an specific way to do this, using SMO (SQL Server management objects)
You can get the collection of tables in the database, and then read the properties of the table you're interested in (columns, keys, and all imaginable properties)
This is what SSMS uses to get and set properties of all database objects.
Look at this references:
Database.Tables Property
Table class
This is a full example of how to get table properties:
Retrieving SQL Server 2005 Database Info Using SMO: Database Info, Table Info
This will allow you to get all the possible information from the database in a very easy way. there are plenty of samples in VB.NET and C#.
I would try something like this. This ensures all items are cleaned up - and avoids using DataReader. You don't need this unless you have unusually large amounts of data that would cause memory issues.
public void DoWork(string connectionstring)
{
DataTable dt = new DataTable("MyData");
using (var connection = new SqlConnection(connectionstring))
{
connection.Open();
string commandtext = "SELECT * FROM MyTable";
using(var adapter = new SqlDataAdapter(commandtext, connection))
{
adapter.Fill(dt);
}
connection.Close();
}
Console.WriteLine(dt.Rows.Count);
}

Right way to export multiple records to Access using OLEDB

I don't know much about exporting data using OLEDB, I figured the following:
using (OleDbConnection conn = new OleDbConnection(connString))
{
try
{
conn.Open();
foreach (T t in rows)
{
using( OleDbCommand oleDbCommand = new OleDbCommand(insertString, conn))
{
OleDbParameter param = new OleDbParameter(.., ..);
oleDbCommand.Parameters.Add(param);
//add more parameters
oleDbCommand.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
//handle
}
}
At first, I didn't use the using statement for the OleDbCommand (i.e., I didn't dispose of the OleDbCommand). But in that case, a record locking file remained on the database even though I was finished exporting. WITH the (inner) Using statement however, exporting seems slower. Why? And how to get both the fast exporting and the removal of the record locking at the end of exporting?
Since you do not close the Connection, the ldb file remains present as you're still connected to the DB.
So, you should put a using statement around the connection-declaration (or close the connection in the finally block of your try statement [which is exactly what the using statement does nb).
using( var conn = new OleDbConnection (connectionstring) )
{
conn.Open();
using( cmd = conn.CreateCommand() )
{
cmd.Parameters.Add (..);
...
for( ... )
{
cmd.Parameters.Clear();
cmd.CommandText = "";
cmd.Parameters["#p_param"].Value = ...
cmd.ExecuteNonQuery();
}
}
}
With the using clause in the for-loop, you're disposing the OleDbCommand for every record that you're going to insert. However, you can re-use the OleDbCommand instance for every insert. (See code above).
Next to that, you should start a transaction explicitly. Since, when you do not do that, an implicit transaction will be created for each insert statement.
Also, by performing all the inserts inside one transaction, you'll be able to rollback all the changes (inserts) that you've done when you encounter an error.
(For instance, if inserting row nr 159 fails, you can rollback all the 158 inserts that you've done before).

Categories