Just wondering, Would the SqlConnection be diposed/closed when this method is done? Or do i have to explicitly call the close method at the end?
using (SqlCommand cmd = new SqlCommand(sql, GetConnection()))
{
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
}
}
SqlConnection GetConnetion()
{
return new SqlConnection("connectionstring");
}
I know i can do something like this:
SqlConnection conn = GetConnetion();
SqlCommand cmd =new SqlCommand(sql, conn);
//Do Something
conn.Close()
cmd.Dispose()
But just curious how the using block will work in this case.
Cheers
No, the connection object won't be automatically disposed in your example. The using block only applies to the SqlCommand object, not the connection.
To ensure that the connection is disposed, make sure that the SqlConnection object is wrapped in its own using block:
using (SqlConnection conn = GetConnection())
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
// don't forget to actually open the connection before using it
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something
}
}
}
Luke's answer is the correct one in terms of what you specifically asked regarding the disposal of the connection.
For completeness, what you could also do is to use the SqlCommand.ExecuteReader(CommandBehaviour) method instead of the parameterless one, passing in CommandBehvaiour.CloseConnection:
using (SqlCommand cmd = new SqlCommand(sql, GetConnection()))
{
using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{}
}
}
This signifies that when the SqlDataReader is closed (when it is disposed of in the using construct), it will in turn close the connection that it is using.
I'm not keen on this approach though, as there is some implied logic and it is not obvious what exactly is closing the connection.
The using statement will take care of this for you.
Oops. You want to use the using on your connection, not on your command.
Use using but on the connection, not on the SqlCommand. The Dispose method on the connection will close the connection (return it to the pool, if pooling is enabled). Also place an using around the SqlDataReader too:
using(SqlConnection conn = GetConnection())
{
SqlCommand cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader())
{
do
{
while (reader.Read())
{
}
} while (reader.NextResult());
}
}
Here and Here is something which could help you understanding what is going on.
Related
I am working on created a login form for an application I am working on. I have my application set up to properly connect to the database and run stored procedures and queries on the database as well.
However I am unsure how to send messages from the database to my VB.Net Application. Right now I have essentially two methods that execute code for my database:
Public Function ExecuteCMD(ByRef CMD As SqlCommand) As DataTable
Dim DS As New DataSet()
Try
OpenDBConnection()
CMD.Connection = DB_CONNECTION
If CMD.CommandText.Contains(" ") Then
CMD.CommandType = CommandType.Text
Else
CMD.CommandType = CommandType.StoredProcedure
End If
Dim adapter As New SqlDataAdapter(CMD)
adapter.SelectCommand.CommandTimeout = 300
adapter.Fill(DS)
Catch ex As Exception
Throw New Exception("Database Error: " & ex.Message)
Finally
CloseDBConnection()
End Try
Return DS.Tables(0)
End Function
Public Function ExecuteCMDWithReturnValue(ByRef CMD As SqlCommand) As Boolean
Try
OpenDBConnection()
CMD.Connection = DB_CONNECTION
CMD.Parameters.Add("#ret", SqlDbType.Int).Direction = ParameterDirection.ReturnValue
CMD.CommandType = CommandType.StoredProcedure
CMD.ExecuteNonQuery()
Dim result As Object = CMD.Parameters("#ret").Value
Return If(Convert.ToInt32(result) = 1, False, True)
Catch ex As Exception
Throw New Exception("Database Error: " & ex.Message)
Return False
Finally
CloseDBConnection()
End Try
End Function
These functions honestly work fine, but they are horrible for error processing.
For example I'd like to be able to set up my Store Procedure for logging in to the application to return a "Username not found" or "Password incorrect" message so that I can display to my user exactly what the problem is, as opposed to just returning a generic "Login information incorrect" message from only returning true or false on the logging in going through or not.
I unfortunately do not know exactly how to do this on either end. I don't know what to set up on the SQL Server side to have it spit out messages in procedures, and I don't know hot to receive those messages in VB.Net.
You can verify your user right in VB. I don't think it is a good idea to tell the user If the password or user name is wrong (or if both are wrong). If this data is password protected then it should be protected from malicious logins. It would help a hacker to know what was wrong.
Private Function VerifyPassword(pword As String, uname As String) As Boolean
Using cn As New SqlConnection(My.Settings.UsersConnectionString)
Dim cmd As New SqlCommand("Select Count(*) From Users Where UserName = #UserName And UserPassword = #Password;", cn)
cmd.Parameters.Add("#UserName", SqlDbType.VarChar, 100).Value = uname
cmd.Parameters.Add("#Password", SqlDbType.VarChar, 100).Value = pword
Try
cn.Open()
Dim i As Integer = CInt(cmd.ExecuteScalar())
If i > 0 Then Return True
Return False
Catch ex As Exception
Throw
Finally
cn.Close()
cmd.Dispose()
End Try
End Using
End Function
Of course the password is stored hashed with a salt.
I'm using sql application roles from a .net application. I have an issue which occurs when the connection is lost. So as an example I have this block of code which opens a connection, sets the app role, does a select from the database and the disposes my connection. If I run this code a 2nd time it fails when trying to set the app role again (the ExecuteNonQuery() line for the sys.sp_setapprole).
The exception is an SqlException: A severe error occurred on the current command. The results, if any, should be discarded.
I've tried using the #fCreateCookie parameter and calling sys.sp_unsetapprole to reset the role but this makes no difference.
Help please?
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("sys.sp_setapprole", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#rolename", "MyRole");
command.Parameters.AddWithValue("#password", "MyPassword");
command.ExecuteNonQuery();
}
try
{
DataSet ds = new DataSet();
using (SqlCommand command = new SqlCommand("dbo.MyProcedure", connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.CommandType = CommandType.StoredProcedure;
adapter.Fill(ds);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am using a connection class for my connection and then I call the class for connecting.
After I use the connection several times it freezes and then gives a error. It seems I have got to many connections open at the same time I can't figure out how tho close the open connections. If that is the real problem.
MyConnection class:
public class MyConnection
{
private SqlConnection _con;
public SqlCommand Cmd;
private SqlDataAdapter _da;
private DataTable _dt;
public MyConnection()
{
_con = new SqlConnection("Data Source=192.168.1.12\\grs;Initial Catalog=BGI;Persist Security Info=True;User ID=awplanung;Password=pass");
_con.Open();
}
public void SqlQuery(string queryText)
{
Cmd = new SqlCommand(queryText, _con);
}
public DataTable QueryEx()
{
_da = new SqlDataAdapter(Cmd);
_dt = new DataTable();
_da.Fill(_dt);
return _dt;
}
public void NonQueryEx()
{
Cmd.ExecuteNonQuery();
}
}
And now I call this connection from my forms: like this one.
MyConnection con = new MyConnection();
con.SqlQuery("SELECT ARartikelnr ,ARartikelbezeich, ARartwarengruppe, ARanzahleinheiten, ARinhalteinheiten, ARanzgebindepal FROM BGARTIKEL where ARartikelnr BETWEEN '" + textBox2.Text + "' and '" + textBox3.Text + "' order by ARinhalteinheiten, ARartwarengruppe");
dt = con.QueryEx();
Each time I open a new form I make a
MyConnection con = new MyConnection();
and make many similar
con.SqlQuery("Select string")
After I open a second form it freezes when I do a new long select. What is strange is that I have used these 2 forms without problems, but in the first one I made a datagrid fill with a button. and now i changed if to fill directly from the form load. and when i go to the next form i cant fill my other datagrid on the new form giving that error.
Error:
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Make your MyConnection class disposable. And dispose it when you are done with data.
implement IDisposable interface on class
(public class MyConnection : IDisposable)
implement Dispose method where dispose your connection
public void Dispose()
{
_con.Dispose();
}
and use it like this
using(MyConnection con = new MyConnection())
{
con.SqlQuery("...");
dt = con.QueryEx();
}
This question has been addressed all over the web and I tried a lot of things without success. The SQL EXPRESS service is setup to accept local system account but the problem still exists.
This is my connection string:
<add name="PhoneTemplateChange" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;Database=PhoneTemplateChange;Integrated Security=SSPI" />
I created a class to do database operations in the constructor I have
_connectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["PhoneTemplateChange"].ConnectionString;
and a method in this class to insert data
public void AddNewChangeOrder(int operation, int targetExt)
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
string sql = "INSERT into [dbo].ChangeOrder (operation, targetExt, dtrequested) VALUES (#operation, #targetExt, #dtrequested)";
using (SqlCommand cmd = new SqlCommand(sql))
{
try
{
cmd.Parameters.AddWithValue("#operation", operation);
cmd.Parameters.AddWithValue("#targetExt", targetExt);
cmd.Parameters.AddWithValue("dtrequested", DateTime.Now);
//con.CreateCommand();
con.Open();
//cmd.InitializeLifetimeService();
int rows = cmd.ExecuteNonQuery();
con.Close();
}
catch (SqlException e)
{
throw new Exception(e.Message);
}
}
}
I have played around with the connection string trying all different suggestions, also the commented code in the method above is what I tried to solve the problem. Still no luck!
I also changed the connection string I get two different exceptions this way
Database=PhoneTemplateChange
The above gives the exception in the title.
And the following gives the Exception "Cannot open Database PhoneTemplatechange.mdf requested by the login. Login failed for user 'mydomain\myusername'"
Database=PhoneTemplateChange.mdf
Any ideas?
You are missing the line of code where you specify that cmd uses con as it's connection. As a result the Command (cmd) has no connection, and con isn't associated with any command at all.
Add this line before executing:
cmd.Connection - con;
Alternatively (and better IMO) change your using statement as follows:
using (SqlCommand cmd = new SqlCommand(sql, con))
I've .NET web service using C#, and I post the result from this web service in JSON Array variable, but there is something strange with my result its not pure JSON variable. How to change it into pure JSON variable?
here is my code:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public ModelReport.Report[] GetReports()
{
List<ModelReport.Report> reports = new List<ModelReport.Report>();
string connectionString = ConfigurationManager.ConnectionStrings["ConnWf"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "select type, sum(OrderQty) as total from tbl_weeklyflash_ID where type <> 'NULL' group by type";
connection.Open();
SqlCommand command = new SqlCommand(sql, connection);
command.CommandText = sql;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
ModelReport.Report report = new ModelReport.Report();
report.type = reader["type"].ToString();
report.total = reader["total"].ToString();
reports.Add(report);
}
}
}
return reports.ToArray();
}
here is my current web service result:
-<string>[{"total":"209480","type":"ESL500ML"},{"total":"10177","type":"CHEESE1K"},{"total":"2719928","type":"ESL"},{"total":"145920","type":"WHP"},{"total":"417236.136","type":"UHT"}]</string>
and I want to change it into:
{"report":[{"total":"209480","type":"ESL500ML"},{"total":"10177","type":"CHEESE1K"},{"total":"2719928","type":"ESL"},{"total":"145920","type":"WHP"},{"total":"417236.136","type":"UHT"}]}
Try building a WCF service. Refer Making of JSON Webservice using C#.NET.
You can learn to create WCF services using this.
Hope it helps.