I have a program which would use the Application Role to write data to a SQL Server 2005.
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlCon;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText =
"EXEC sp_setapprole 'application Role name','password';";
sqlCommand.CommandText += sqlComm;
sqlCommand.CommandTimeout = 300;
sqlCon.Open();
int res = sqlCommand.ExecuteNonQuery();
}
This code is in a loop. for the first time, it's OK. In second iterator, it throws exception.
The connection has been dropped because the principal that opened it subsequently assumed a new security context, and then tried to reset the connection under its impersonated security context. This scenario is not supported. See "Impersonation Overview" in Books Online.
Event ID 18059
Source MSSQLSERVER
Is there anyone meet this problem before?
Best Regards,
turn off connection pooling, explicitly. by default is on and connection pooling does not work with unreversible impersonation like approles.
The using{} statement calls IDispose at the end of the block thus killing your connection.
https://msdn.microsoft.com/en-us/library/yh598w02.aspx
using Statement (C# Reference)
Related
I am trying to create to a local database via a mdf file, like so:
scon = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDBFilename=|DataDirectory|\articles.mdf; Integrated Security=True");
scon.Open();
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)");
scmd.Parameters.AddWithValue("#url", "http://google.com");
scmd.ExecuteNonQuery();
MY mdf file is in the root folder, and in the debug folder too. When I run the following code I get an error saying the following:
I can't use the full connection path because it's a long url with spaces, here is my file structure:
My database exists:
How can I fix this so I can connect to my database?
Pass the connection object to the SqlCommand constructor
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)", scon);
The connectionstring is fine, the error message informs you that it is not possible to execute a command if the database is not known. The SqlConnection contains this information and you need to pass it to your command.
Another possibility is through the
scmd.Connection = scon;
but, personally, I prefer to pass that info in the constructor.
Final but really important note:
SqlConnection and SqlCommand are disposable objects. You should always dispose these kind of objects. The using statement is the correct method
using(scon = new SqlConnection(....))
using(scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)",scon))
{
scon.Open();
scmd.Parameters.AddWithValue("#url", "http://google.com");
scmd.ExecuteNonQuery();
}
The Problem With Your Code Is That You Have A Command and a Connection But There Is Nothing To Till The Command To Use This Connection Object ... You Can Use The SqlCommand Constructor To Do That
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)",scon)
Or Use The Connection Property Of The SqlCommand Class Like This
scmd.Connection = scon
Consider Adding Using To Your SQL Connection ... Or Else You Will Have To Manually Close The Connection By Calling scon.Close();
if You Didn't Do either Of Those You Will Run Into An Exception If Your Tried To Open The Connection Again While It's Already Open
I have a C#, .Net 4.5.2 project, built in VS2012, which uses Entity Framework to connect to a SQL database. I now need to access a separate Oracle database, and have been trying to use SQL Anywhere 16 to make the connection. I know that the SQL Anywhere connection works because I have a test project which successfully uses it. The problem is that the connection.Open() method errors with this message:
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.
I suspect that Entity Framework doesn't like the additional connection, but enabling MSDTC is not an option as I only have FTP access to the server where the code will live. Is anyone able to suggest an alternative way to get this working, bearing in mind I know very little about Entity Framework?
Additional
There aren't any transactions set up as far as I can see (I only wrote the stuff for connecting to the Oracle database), nor is TransactionScope being used. Here's an edited version of my code:
var connectionString = new SAConnectionStringBuilder();
connectionString.Host = "***.***.***.***";
connectionString.DatabaseName = "*****";
connectionString.UserID = "*****";
connectionString.Password = "*****";
connectionString.ServerName = "*****";
using (SAConnection conn = new SAConnection(connectionString))
{
using (SACommand cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
Solution
I did some more searching, and after a bit of trial and error, managed to solve my problem. It seems the SQL Anywhere connection was automatically being put into a transaction. When this was then combined with the transactions being used by the entity framework connection, it was raised to a distributed transaction.
I have found that by putting the connection inside a transaction scope, and using the TransactionScopeOption.Suppress flag, it is no longer being put into a transaction, and therefore does not require MSDTC to be enabled. My code now looks like this:
var connectionString = new SAConnectionStringBuilder();
connectionString.Host = "***.***.***.***";
connectionString.DatabaseName = "*****";
connectionString.UserID = "*****";
connectionString.Password = "*****";
connectionString.ServerName = "*****";
using (TransactionScope scope1 = new TransactionScope(TransactionScope.Suppress))
{
using (SAConnection conn = new SAConnection(connectionString))
{
using (SACommand cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
scope1.Complete();
}
Thanks to everyone who responded
I'm a new developer with c#, I created a c# project and I need to access the SQL database to perform the SELECT statement
and I got this error in this figure
My connection statement is correct, so what's wrong with it ?!
I tried the mentioned solutions and I got this error
does anyone know how to handle it ?!
The error is telling you what to do, your connection is not open yet. Open it like:
con.Open();
Before executing your command.
Couple of things for your code, Use parameterized query, this will save you from SQL Injection, also use using statement which will ensure disposal of connection object.
using (SqlConnection con = new SqlConnection("connection string"))
using(SqlCommand cmd = new SqlCommand("SELECT EmpName FROM Employee WHERE EmpID=#EmpID", con))
{
cmd.Parameters.AddWithValue("#EmpID", id.Text);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
//..... your rest of the code
}
EDIT:
For your edited part of question, you are having issue with your SQL Server not allowing remote connection. You have to enable it.
See: How to enable remote connections in SQL Server
Reader needs open connection
Put con.Open() before executing reader
SqlCommand cmd = newSqlCommand("SELECT EmpName from Employee where EmpID =" +id.Text,con);
con.open(); //Open connection
SqlReader Read = cmd.ExecuteReader();
if (Read.Read())
{
Position =Read[0].tostring();
}
read.close();
con.close();//Close connection after reader finishes reading
con.Dispose();
I created a connection and an SqlReader but forgot to close both of them:
SqlConnection conn = new SqlConnection("connection info");
conn.Open();
string sql = "SQL command HERE";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader reader = cmd.ExecuteReader();
Now when try to run the code again it always gives me this error:
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
This link told me how to properly open and close a connection but didn't explain anything on how to close one still running.
I tried shuting down the pc, I tried looking into the database's options on SQL server (found none useful)... I changed the code to do just the close of both the connection and the reader (it compiled and runned but the problem remained after changing back the code).
How can I close this "ghost" connection? Is there any way (brute force) to close all running connections?
[EDIT:] I couldn't really solve the problem. The workaround was to add MultipleActiveResultSets=true to the connection string
I don't think you can access the ghost object, for future, just use using construct where it's possible:
using(SqlConnection conn = new SqlConnection("connection info"))
{
conn.Open();
string sql = "SQL command HERE";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader reader = cmd.ExecuteReader();
....
}
Wrap the creation in a using statement - this will always ensure the connection gets closed:
using(SqlConnection conn = new SqlConnection("connection info"))
{
// your code
}
Looking at all the answers, they seem to tell you how to avoid the problem.
If I'm not mistaken, what you mean is that a connection exists on both the client (your PC) and the server (The sql server) because you forgot to close it, and you're worried about it hanging out there forever.
Think of your connection to the server as a phone conversation. I could hang up on you, but it takes a few seconds for your phone to realize the connection is lost. You may sit there wondering if I've hung up, or just stopped talking. You really don't know. This is what happens on the server when a connection isn't closed properly. (On older landlines, you could leave the phone off the hook and tied up the line indefinitely.)
By closing the connection in code, you are effectively telling the server to close their end of the connection before closing your own. if you FAIL to close the conneciton, it will be closed on your end when the program exits or if you reboot, but the server may sit there with an open connection. (Think of someone sitting there wondering "Did he just hang up on me?")
If I'm not mistaken, what you want to get to is closing it at the SQL server end. (Getting them to "hang up".)
After rebooting, it is absolutely closed on your end. It should clear on its own at the server.
However, if you want to do it yourself, you can clear it at the server in code end using this info: How do you kill all current connections to a SQL Server 2005 database?
A far easier approach would be to just do it in SQL Server Management Studio as described here: http://www.mikebevers.be/blog/2009/07/kill-open-sql-processes-connections/
All of these answers tell you how to avoid the problem, but they don't explain what the problem is.
A SqlDataReader provides forward-only data access, which means that once you have used it and are done, you must close create a new one. See this blog for a detailed explanation. Basically, if you don't close the DataReader, then underthehood it will remain open dedicated to that connection and command.
As others have stated, its best to ensure you close all your resources.
using (SqlConnection connection = new SqlConnection("...")) {
connection.Open();
string sql = "SQL command HERE";
using (SqlCommand cmd = new SqlCommand(sql, con))
using (SqlDataReader reader = cmd.ExecuteReader()) {
// do your stuff
}
}
Truth be told even when you "close" or "dispose" of a connection it does not really go away unless you explicitly disable Pooling in your connection string. You can however do this
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool.aspx
I know this is an old post, and this may help no one. But I saw a opportunity to post what I saw wrong with this question.
First, you are creating a SqlConnection named conn but in your SqlCommand named cmd you are calling con as your connection. This is a problem:
SqlConnection conn = new SqlConnection("connection info");
conn.Open();
string sql = "SQL command HERE";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader reader = cmd.ExecuteReader();
This might be why it's giving you the error:
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
Second, to close a conn after you are done you use:
conn.Close();
Third, to close a SqlDataReader you use:
reader.Close();
But you just assigned the SqlDataReader to reader. You never actually opened the SqlDataReader. To open it use:
reader.Read();
Or:
while (reader.Read())
{
// Code
}
Now a proper way to initilaize a connection and a SqlDataReader while opening and close them:
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM TableName;";
SqlDataReader reader = cmd.ExecuteReader();
reader.Read();
if (reader.HasRows)
{
strCol1 = reader.GetValue(0).ToString();
}
reader.Close();
}
conn.Close();
}
Since IIS assigns a worker thread for each request I've intention to create new object to serve each request. I have 2 questions:
Is it efficient to create new object to serve each request? (is there even alternatice?)
Is it thread safe, efficient and best practice to create new connection, and open&close it for each request like below:
using (MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT password FROM Admin WHERE username='" + username + "'", conn);
object dbp = cmd.ExecuteScalar();
conn.Close();
}
PS. this example is taken from this site. I use oracle db.
Thanks: Matti
When you do new SomeSqlConnection() you actually don't create a new connection every time. As database connections are expensive to create ADO.NET keeps a connection pool and draws connections from there. You could also remove the call to the Close method. Here's a snippet you can safely use in each request:
var connectionString = ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString;
using (var conn = new MySqlConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT count(*) from some_table";
object result = cmd.ExecuteScalar();
}
As Darin correctly states in his answer, you should allow the connection pooling mechanism to do its job. Don't try and build something 'clever', it won't be as good.
The golden rule with expensive resources such as database connections is to acquire late and release early. As long as you abide by that then you'll do just fine.