I am running C# .NET code where I need to test certain values that have been entered in a web page form and then passed to the server. The server then uses those values
in a query string to return a value. I encase these query instructions within a try-catch block in order to trace any Sql exceptions.
The problem is this:
Once the application has started, the connection string is set, and the query is run, I don't get a stack trace from the catch block's SQL Exception but instead
I just get a blank/empty value within the method that ran the query. The method will return a Boolean variable to indicate if there was any value read from the query and if so it returns true however it always returns false which should not happen because I have checked the query string that it builds by pasting it into MS SQL 2008's Query Console and running it. The results from running the pasted SQL instruction test does produce non-null data from the query. Thank much for your help.
I'm running VS2003 with IIS 6.0 and using MS SQL 2008 Enterprise Studio
Here is the code segment for the web.config and C# code. Thanks much for your help.:
<system.web>
<!-- DYNAMIC DEBUG COMPILATION
Set compilation debug="true" to enable ASPX debugging. Otherwise, setting this value to
false will improve runtime performance of this application.
Set compilation debug="true" to insert debugging symbols (.pdb information)
into the compiled page. Because this creates a larger file that executes
more slowly, you should set this value to true only when debugging and to
false at all other times. For more information, refer to the documentation about
debugging ASP.NET files.
-->
<compilation defaultLanguage="c#" debug="true" />
====================
//This method takes one string and returns either country name or Canadian state as a string, according to query.
private string candStateCountryCheck(string strQuery)
{
string strStateCountry = "";
SqlConnection con = null;
SqlCommand cmd = null;
SqlDataReader sdr = null;
try
{
string strConnection = ConfigurationSettings.AppSettings["OLEDBConnectionString"];
con = new SqlConnection(strConnection);
con.Open();
cmd = new SqlCommand(strQuery, con);
sdr = cmd.ExecuteReader();
if(sdr.Read())
{
strStateCountry = sdr.GetString(0);
}
}
catch (Exception exc)
{
ErrorLabel.Text = "ERROR:" + exc.Message;
}
finally
{
if (sdr != null)
sdr.Close();
if (cmd != null)
cmd.Dispose();
if (con != null)
con.Close();
}
return strStateCountry;
}
This should work, but I think your should use ExecuteScaler for single result queries. I also encourage you to use parameterized queries:
while (sdr.Read())
{
strStateCountry = sdr.GetString(0);
}
ExucuteScaler example:
try
{
string strConnection = ConfigurationSettings.AppSettings["OLEDBConnectionString"];
using(SqlConnection con = new SqlConnection(strConnection))
{
con.Open();
using(SqlCommand cmd = new SqlCommand(strQuery, con))
{
strStateCountry = (String)cmd.ExecuteScalar();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I'll try to avoid anything here that won't work with VS2003, but it's gonna be hard... VS2003 is getting pretty old now, and you know that the express edition of VS2010 is available for free, right?
Also, this is a re-write of your code to show a better example of how it should look, if it were using a fictional database. You did not share any of your database structure, any example data, or what a query might look like, so that's the best we can do for now:
private string candStateCountryCheck(string toTest)
{
string sql = "SELECT countryStateName FROM SomeTable WHERE ItemKey LIKE #Query + '%';";
try
{
string strConnection = ConfigurationSettings.AppSettings["OLEDBConnectionString"];
con = new SqlConnection(strConnection);
cmd = new SqlCommand(sql, con);
cmd.Parameters.Add("#Query", SqlDbType.VarChar, 50).Value = toTest;
con.Open();
return cmd.ExecuteScalar().ToString();
}
catch (Exception exc)
{
ErrorLabel.Text = "ERROR:" + exc.Message;
}
finally
{
cmd.Dispose();
con.Dispose();
}
}
You NEVER want to write methods that expect fully-formed sql code as arguments.
Related
I have created one sp that tuncate table.Table name is dynamic.Here I used dynamic sql.Sp is working fine.I want to execute that sp from C#.net(from cs file).
I know executenonquery returns no of row affected.executenonquery is used for insert,update and delete command.Exectesclare is used for select which has only one cell.EceuteReader is used for selecting multiple record.What shall i use that tell my tuncate table clause executed properly or not?
You can use ExecuteNonQuery to truncate the table.
try
{
string connectionString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string commandText = "TRUNCATE TABLE myTable";
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.ExecuteNonQuery();
lblStatus.Text = "Table Deleted Successfully.";
}
}
}
catch(Exception ex)
{
lblStatus.Text = "Table can not be deleted, Error " + ex.Message;
}
I suppose the best way is to use ExecuteNonQuery.
1. It returs the number of rows affected by the statement.
2. And if something doesn't work properly, you will get a nice SqlException which won't go by unnoticed.
try
{
procedure.ExecuteNonQuery();
nextStep.ExecuteWhatever();
}
catch(SqlException e)
{
Console.WriteLine("Oh noes!");
}
I have an ASP.NET web page. It makes use of 4 BackgroundWorkers. Each bw retrieves some data from a database.
The code for connecting to the database is:
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
DataTable dt = new DataTable();
OdbcCommand cmd = new OdbcCommand(sqlQuery, dbConnection);
cmd.CommandTimeout = 0;
IDataReader dataReader = cmd.ExecuteReader();
dt.Load(dataReader);
dataReader.Close();
dataReader.Dispose();
In the constructor, this.dbConnection = new OdbcConnection(networkdetails);
Each bw makes use of the above code snippet to query the database and retrieve the values. The code works perfectly fine sometimes. Other times it throws the exception given above.
Any help as to what I may be doing wrong?
Try to handle the exception and then close the connection.
For this, write your code in 'Try' block, catch the exception in 'Catch' block and close the connection in 'Finally' block.
try{
// Your code
}
catch
{
// Catch exception
}
Finally
{
// Close the connection
dbConnection.Close();
}
I'm using Asp.net c# and MYSql as back-end. I'm updating a table,but table is not updating.There are only 3 columns in the table.
There is no exception when I'm executing the command object. But this returns 0 value from cmd.ExecuteNonQuery().
I debugged this and found cmd.Parameters are full with values. and if i manually run the update command in mysql it works fine.
the table is as follow
column -- Datatype
ShortText -- varchar
title -- varchar
id -- int
Please guide me...
int retVal = 0;
string shortText = ((TextBox)fmvwShortText.FindControl("txtShortText")).Text.Trim();
try
{
int id = Convert.ToInt32(((Label)fmvwShortText.FindControl("lblShrtTextID")).Text);
MySqlConnection con = new MySqlConnection(System.Configuration.ConfigurationManager.AppSettings["conn"]);
cmd = new MySqlCommand();
cmd.Connection = con;
cmd.CommandText = "UPDATE temp_posts SET ShortText=#shrtText WHERE id=#id AND Title=#title";
cmd.Parameters.Add("#shrtText", MySqlDbType.VarChar).Value = shortText;
cmd.Parameters.Add("#title", MySqlDbType.VarChar).Value =Session["EditTitle"].ToString();
cmd.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
con.Open();
retVal = cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception e) { }
return retVal;
Is it possibly a casing issue with your Title parameter? I notice you are only updating if the ID & Title match exactly?
Also as a general rule of thumb, when using objects which implement IDisposable you should wrap them with a using statement, this will make sure your objects are always disposed (even on the result of an error)
using (var con = new MySqlConnection(...))
{
using (var cmd = new MySqlCommand(...))
{
....
}
}
First of all thank you every one who kept looking and tried their best to sort out this problem with me..
Finally got the solution.
In my code I used # in cmd.CommandText and in parameters.
But when I replace this # with ? both in cmd.CommandText and in parameters and used the cmd.ExecuteScalar(); this worked.
Actually Parameter names depend on the provider. When using the provider for
SQL Server, it should start with # (e.g. #param1). For Oracle
provider, it should start with a colon (...for e.g. aram1. For
OleDb provider, just a question mark (?) would work
Thank you everyone to contribute your best... many thanks
But i'm still left with a question that ExecuteScalar() is updating the records in the database? I am with no answer... looking for this.
Try this nt sure about code formating coz currently am not using ide frmwrk
int retVal = 0;
string shortText = ((TextBox)fmvwShortText.FindControl("txtShortText")).Text.Trim();
try
{
int id = Convert.ToInt32(((Label)fmvwShortText.FindControl("lblShrtTextID")).Text);
MySqlConnection con = new MySqlConnection(System.Configuration.ConfigurationManager.AppSettings["conn"]);
cmd = new MySqlCommand("UPDATE temp_posts SET ShortText='"+shortText+"' WHERE id='"+id+"' AND Title='"+Session["EditTitle"].ToString()+"'",con);
con.Open();
retVal = cmd.ExecuteNonQuery();
con.Close();
return retVal;
}
catch (Exception e) { }
I identified a bug in my code and I'm baffled as to how it could have occurred in the first place.
My question is, I found a skip in the database ID fields (it is an incremented identity field), indicating some records weren't inserted - which means my SQL sprocs (probably) threw an error. Thinking backwards from there, that means that my business object should have caught that error and thrown it, exiting immediately and returning back to the page's codebehind (instead it continued right on to the second stored procedure). I don't understand why or how this is possible. What's going on in respect to the code execution skipping my try catches?
Page code behind:
protected void submitbutton_click(object sender, EventArgs e){
try{
mybusinessobject.savetodatabase()
} catch( Exception ex) {
Response.Redirect("Error.aspx");
}
}
business object code:
public static void savetodatabase(){
int ID1=-1;
int ID2=-1;
//store the billing contact
SqlCommand cmd1 = new SqlCommand("SaveInfo1", con);
cmd1.CommandType = CommandType.StoredProcedure;
//...
cmd1.Parameters.Add("#Ret", SqlDbType.Int);
cmd1.Parameters["#Ret"].Direction = ParameterDirection.ReturnValue;
try
{
con.Open();
cmd1 .ExecuteNonQuery();
ID1 = Convert.ToInt32(cmd1.Parameters["#Ret"].Value);
}
catch (Exception ex) { throw ex; }
finally { con.Close(); }
if (ID1 > 0)
{
SqlCommand cmd = new SqlCommand("SaveInfo2", con);
cmd.CommandType = CommandType.StoredProcedure;
//...
try
{
con.Open();
cmd.ExecuteNonQuery();
ID2= Convert.ToInt32(cmd.Parameters["#Ret"].Value);
}
catch (Exception ex) { throw ex; }
finally { con.Close(); }
}
}
SQL Code:
PROCEDURE [dbo].[SaveInfo1]
(
-- ... parameters ...
)
AS
INSERT INTO Table1 ( ... ) Values ( ... )
RETURN SCOPE_IDENTITY
PROCEDURE [dbo].[SaveInfo2]
(
-- ... parameters ...
)
AS
DECLARE #SpecialID INT
INSERT INTO Table2 ( ... ) Values ( ... )
SET #SpecialID = SCOPE_IDENTITY()
INSERT INTO Table3 ( [ID], ... ) Values ( #SpecialID, ... )
RETURN SCOPE_IDENTITY()
Your exception handling is horrible. Never do this:
catch (Exception ex) { throw ex; }
All that accomplishes is to screw up the stack trace in the exception. It makes it look like the exception originated at the point of the throw.
Never do this:
try{
mybusinessobject.savetodatabase()
} catch( Exception ex) {
Response.Redirect("Error.aspx");
}
You don't know what exception happened. You have no idea whether or not it's safe to redirect, and on top of it all, you lose all information about what the exception was!
You should also get into the habit of implementing using blocks:
public static void savetodatabase()
{
using (SqlConnection con = new SqlConnection("Connectionstring"))
{
int ID1;
//store the billing contact
using (SqlCommand cmd1 = new SqlCommand("SaveInfo1", con))
{
cmd1.CommandType = CommandType.StoredProcedure;
//...
cmd1.Parameters.Add("#Ret", SqlDbType.Int);
cmd1.Parameters["#Ret"].Direction = ParameterDirection.ReturnValue;
con.Open();
cmd1.ExecuteNonQuery();
ID1 = Convert.ToInt32(cmd1.Parameters["#Ret"].Value);
}
if (ID1 <= 0)
{
return;
}
int ID2 = -1;
using (SqlCommand cmd = new SqlCommand("SaveInfo2", con))
{
cmd.CommandType = CommandType.StoredProcedure;
//...
con.Open();
cmd.ExecuteNonQuery();
ID2 = Convert.ToInt32(cmd.Parameters["#Ret"].Value);
}
}
}
A using block will ensure that the resource will have its Dispose method called, whether or not an exception is thrown.
Isn't the more likely scenario that someone just deleted some records from the table?
If records are deleted, their unique identifiers will not be recycled, even when new records are later inserted. You can use RESEED in SQL to reset the identity seed to 0 if you desire, but I suggest against that unless you wipe the table. Otherwise you could end up with primary key violations.
Also, make sure your column's identity seed is set to increment 1 at a time.
Your code doesn't matter, just go to Web.config and play with appropriate node:
<customErrors mode="On|Off" />
P.S.
Use the using clause to auto-close a connection, instead of manual in the finally clause
you can test the catch. just change the procedure:
PROCEDURE [dbo].[SaveInfo1]
(
-- ... parameters ...
)
AS
INSERT INTO Table1 ( ... ) Values ( ..., some_out_of_range_value_here, ....)
RETURN SCOPE_IDENTITY()
to have some hard coded out of range value (so the insert fails), and then run your application...
I have a generic method to call a stored Procedure in ASP.NET:
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlDataReader iReader;
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
iReader = sql.ExecuteReader(CommandBehavior.CloseConnection);
sql.Dispose();
return iReader;
}
Even though I am calling CommandBehavior.CloseConnection the connection is not closing. I can get the data fine the first time I request a page. On reload I get the following error:
The connection was not closed. The
connection's current state is open.
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.
Exception Details:
System.InvalidOperationException: The
connection was not closed. The
connection's current state is open.
Source Error:
Line 35: Line 36: } Line
37: sql.Connection.Open();
Line 38: iReader =
sql.ExecuteReader(CommandBehavior.CloseConnection);
Line 39: sql.Dispose();
Finally if I put sql.Connection.Close(); before sql.Dispose(); I get an error that iReader is not readable because it's been closed already.
Obviously I am closing my connection incorrectly, can someone point me in the right direction?
When you return a DataReader, the underlying connection must remain open. It's the consumer's responsibility to properly clean up resources.
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
return sql.ExecuteReader(CommandBehavior.CloseConnection);
}
public void ConsumingMethod()
{
using(SqlDataReader reader = ExecuteStoredProc("MyProc", params))
{
while(reader.Read())
{
//work with your reader
}
}
}
I would suggest wrap the sql connection with a "using" statement, and that will take care of most sql connection issue.
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
The idea is to do a Connection.Close(); after you've finished with the SqlReader, so basically instead of placing the close() statement before the SqlReader.Dispose() command, you should place it below.
This is my preferred way to process IDataReader. Let the caller creates SqlConnection instance and passes to methods.
It's expensive to create SqlConnection instance. And you’ll end up code call the same ExecuteStoredProc method multiple times in different situation.
Thus, I refactor ExecuteStoredProc method by adding SqlConnection instance as part of the parameter.
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = // Connection String;
conn.Open();
using (IDataReader reader = foo.ExecuteStoredProc(conn, sprocName, SqlP))
{
// Process IDataReader
}
}