We use oracle database connection and our class database access does not have a dispose or close. It interferes with something or performance of the application? I saw this example:
string oradb = "Data Source=ORCL;User Id=hr;Password=hr;";
OracleConnection conn = new OracleConnection(oradb); // C#
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "select * from departments";
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
label1.Text = dr.GetString(0);
conn.Dispose();
And I realized that it opens the connection and then kills her. This is correct? Is there any other better?
I'm leaving my connection open and then ends up being closed for a while. I think that's it. This so wrong?
Use the Using statement with disposable objects. In particular with any kind of connection and datareaders
string oradb = "Data Source=ORCL;User Id=hr;Password=hr;";
using(OracleConnection conn = new OracleConnection(oradb))
using(OracleCommand cmd = new OracleCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "select * from departments";
cmd.CommandType = CommandType.Text;
using(OracleDataReader dr = cmd.ExecuteReader())
{
dr.Read();
label1.Text = dr.GetString(0);
}
}
Here you could read about the Using statement and why it is important. Regarding the connection and readers, you should enclose the objects with the using statement to be sure that everything is properly closed and disposed when you exit from the using block ALSO in case of exceptions
Related
I have a problem in SqlDataReader - it cannot proceed into while and cannot while.
Here is my code
List<tmp_WatchList> data = new List<tmp_WatchList>();
using (SqlConnection con = new SqlConnection(conStr))
{
using (SqlCommand cmd = new SqlCommand("sp_CheckPersonList", con))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = name;
SqlDataReader oReader = cmd.ExecuteReader();
while (oReader.Read())
{
//data.Add(new tmp_WatchList
//{
tmp_WatchList l = new tmp_WatchList();
l.id = int.Parse(oReader["id"].ToString());
l.Name = oReader.GetValue(1).ToString();
l.Crime = int.Parse(oReader.GetValue(2).ToString());
data.Add(l);
///});
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
con.Close();
}
}
}
and my stored procedure is:
ALTER PROCEDURE [dbo].[sp_CheckPersonList]
(#Name NVARCHAR(MAX) NULL)
AS
BEGIN
SELECT REPLACE(Name, '.', ''), Crime
FROM [dbo].[tmp_WatchList]
WHERE [Name] LIKE CONCAT('%', REPLACE(#Name, ' ', '%'), '%')
END
Can you tell me how it is done? Or is something wrong with my structure?
You are not opening the connection any where before calling the ExecuteReader, you need to open the database connection, following is the lineo of code to open the connection :
con.Open(); // open connection
SqlDataReader oReader = cmd.ExecuteReader(); // now execute SP
and you do not need finally block for closing the connection, as you are already applyuing the using block on your SqlConnection and SqlCommand which is converted by compiler in to try finally which takes care of disposing the resources and in case of SqlConnection closing the connection.
As other have pointed out, you need to Open the connection, and you can simplify your code removing the try/catch/finally and the explicit con.Close(), which you don't need since you are (corretcly) wrapping the connection within a using
Your code should be something like this (much cleaner than the original one after removing the try/catch/finally):
List<tmp_WatchList> data = new List<tmp_WatchList>();
using (SqlConnection con = new SqlConnection(conStr))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("sp_CheckPersonList", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = name;
SqlDataReader oReader = cmd.ExecuteReader();
while (oReader.Read())
{
tmp_WatchList l = new tmp_WatchList();
l.id = int.Parse(oReader["id"].ToString());
l.Name = oReader.GetValue(1).ToString();
l.Crime = int.Parse(oReader.GetValue(2).ToString());
data.Add(l);
}
}
}
If that code raises an exception, it will simply be forwarded to the caller, in a better way comparing to what you did with your throw new Exception(exc.Message), which will loose the original stack trace
Remove the unwanted code..Try Like this..
List<tmp_WatchList> data = new List<tmp_WatchList>();
SqlConnection con = new SqlConnection(conStr);
SqlCommand cmd=new SqlCommand();
cmd.CommmandText="sp_CheckPersonList";
cmd.CommandType = CommandType.Text;
con.Open();
cmd.Connection = con;
cmd.Parameters.AddWithValue("#Name",name);
SqlDataReader oReader = cmd.ExecuteReader();
while (oReader.Read())
{
tmp_WatchList l = new tmp_WatchList();
l.id = int.Parse(oReader["id"].ToString());
l.Name = oReader.GetValue(1).ToString();
l.Crime = int.Parse(oReader.GetValue(2).ToString());
data.Add(l);
}
oReader.Close();
Con.Close();
My code gets to conn.Open and gives me "Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll"
Here is the block of code:
_timer.Stop();
string path = #"C:\testlog.log";
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MYDB_Conn"].ConnectionString);
string query = "SELECT RawImportEnabled, ImportDayTimeStamp from Settings";
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open(); // Dies here
SqlDataReader rdr = cmd.ExecuteReader();
Order is missing ...first open connection then use sql command
_timer.Stop();
string path = #"C:\testlog.log";
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MYDB_Conn"].ConnectionString);
conn.Open(); // sholud be here
string query = "SELECT RawImportEnabled, ImportDayTimeStamp from Settings";
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader rdr = cmd.ExecuteReader();
Besides your code is not formatted either..Format like this
string path = #"C:\testlog.log";
String connectionString = ConfigurationManager.ConnectionStrings["MYDB_Conn"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open(); // sholud be here
string query = "SELECT RawImportEnabled, ImportDayTimeStamp from Settings";
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
String RawImportEnabled = Convert.ToString(reader["RawImportEnabled"]);
//Do some thing
}
}
This has some benefits like debugging the connection string by putting a breakpoints ,Disposal of connection without worrying for using statements etc
_timer.Stop();
string path = #"C:\testlog.log";
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MYDB_Conn"].ConnectionString);
string query = "SELECT RawImportEnabled, ImportDayTimeStamp from Settings";
conn.Open(); // Dies here again.
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.HasRows)
I need to make asmx web service. I installed ODAC from here
Then, i add references to my project:
1) Oracle.DataAccess
2) Oracle.Web
[WebMethod]
public string EaaTest(string r_object_id)
{
string connString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)" +
"(HOST=my host)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=dcmt)));" +
"User Id=my id ;Password=my password;"
using (OracleConnection conn = new OracleConnection(connString))
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = string.Format("select DSS_TITLE_RU from DBREP36.DDT_DA_DIRECTION_S where R_OBJECT_ID=0", r_object_id);
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
string result = dr.GetString(0);
return result;
}
}
Now, i have exception:
An exception of type 'System.InvalidOperationException' occurred in
Oracle.DataAccess.dll but was not handled in user code
Additional information: Connection must be open for this operation
On line: OracleDataReader dr = cmd.ExecuteReader();
Error message isn't clear at all?
Connection must be open for this operation
You need to open your connection before you execute your command.
conn.Open();
OracleDataReader dr = cmd.ExecuteReader();
Use using statement to dispose your command and reader as you did for your connection.
By the way, you didn't specify zero index in your string.Format. Your
where R_OBJECT_ID=0
should be
where R_OBJECT_ID = {0}
As a better option, use parameterized queries. Any kind of string concatenations are open for SQL Injection attacks.
Since you return just first column of the first row, use ExecuteScalar instead which is exactly what this for.
using(var conn = new OracleConnection(connString))
using(var cmd = conn.CreateCommand())
{
cmd.CommandText = #"select DSS_TITLE_RU from DBREP36.DDT_DA_DIRECTION_S
where R_OBJECT_ID = #id";
cmd.Parameters.AddWithValue(#id, r_object_id);
conn.Open();
return (string)cmd.ExecuteScalar();
}
I'm trying to prevent SQL injections. Am I doing this right? (I'm using MS Access.) Should I still use sqlparameter?
OleDbParameter[] myparm = new OleDbParameter[2];
myparm[0] = new OleDbParameter("#UserID", UserName.Text);
myparm[1] = new OleDbParameter("#Password", encode);
string queryStr = "SELECT * FROM TMUser WHERE UserID=#UserID AND Password=#Password";
OleDbConnection conn = new OleDbConnection(_connStr);
OleDbCommand cmd = new OleDbCommand(queryStr, conn);
conn.Open();
OleDbDataReader dr = cmd.ExecuteReader();
Close!
string queryStr = "SELECT * FROM TMUser WHERE UserID=#UserID AND Password=#Password";
OleDbConnection conn = new OleDbConnection(_connStr);
OleDbCommand cmd = new OleDbCommand(queryStr, conn);
cmd.Parameters.AddWithValue("#UserID", UserName.Text);
cmd.Parameters.AddWithValue("#Password", encode);
The parameters are part of the command object and you use the Parameters.AddWithValue method to set the parameter values to what you have defined in the query string.
By the way, you should be using using statements to encapsulate some of your objects, here is what I typically do:
using (OleDbConnection conn = new OleDbConnection(_connStr))
using (OleDbCommand = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT ...";
cmd.Parameters.AddWithValue(...);
cmd.ExecuteReader();
//...
}
That way you don't have to worry about cleaning up resources if something goes wrong inside or closing the connection when you are done.
I have question about using why i can not use the same instance of SQLCommand more than one time in the same code?
I tried the code down here and it runs good for the gridview but when i changed the query by using cmd.CommandText() method it keeps saying:
There is already an open DataReader associated with this Command which must be closed first.
This is the code:
string cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
SqlConnection con = new SqlConnection(cs);
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = "Select top 10 FirstName, LastName, Address, City, State from Customers";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
}
catch(Exception exp)
{
Response.Write(exp.Message);
}
finally
{
con.Close();
}
The problem is that you are using the SqlCommand object to generate a DataReader via the command.ExecuteReader() command. While that is open, you can't re-use the command.
This should work:
using (var reader = cmd.ExecuteReader())
{
GridView1.DataSource = reader;
GridView1.DataBind();
}
//now the DataReader is closed/disposed and can re-use command
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
There is already an open DataReader associated with this Command which must be closed first.
This is the very reason you don't share a command. Somewhere in your code you did this:
cmd.ExecuteReader();
but you didn't leverage the using statement around the command because you wanted to share it. You can't do that. See, ExecuteReader leaves a connection to the server open while you read one row at a time; however that command is locked now because it's stateful at this point. The proper approach, always, is this:
using (SqlConnection c = new SqlConnection(cString))
{
using (SqlCommand cmd = new SqlCommand(sql, c))
{
// inside of here you can use ExecuteReader
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// use the reader
}
}
}
These are unmanaged resources and need to be handled with care. That's why wrapping them with the using is imperative.
Do not share these objects. Build them, open them, use them, and dispose them.
By leveraging the using you will never have to worry about getting these objects closed and disposed.
Your code, written a little differently:
var cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
var gridSql = "Select top 10 FirstName, LastName, Address, City, State from Customers";
var cntSql = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
try
{
using (SqlCommand cmd = new SqlCommand(gridSql, con))
{
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
using (SqlCommand cmd = new SqlCommand(cntSql, con))
{
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
}
}
catch(Exception exp)
{
Response.Write(exp.Message);
}
}
Thank u quys but for the guys who where talking about using block !
why this code work fine which i seen it on example on a video ! It's the same thing using the same instance of SqlCommand and passing diffrent queries by using the method CommanText with the same instance of SqlCommand and it's execute just fine , this is the code :
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = "Delete from tbleProduct where ProductID= 4";
int TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
cmd.CommandText = "Insert into tbleProduct values (4, 'Calculator', 100, 230)";
TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
cmd.CommandText = "ypdate tbleProduct set QtyAvailbe = 234 where ProductID = 2";
TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
}