I am trying to save this to my datebase but I keep getting this error
System.InvalidOperationException
here is my code.
protected void btnSend_Click(object sender, EventArgs e)
{
con.Open();
cmd = new SqlCommand(#"INSERT INTO orders2
(orderName,orderFile,orderType,orderPrice,orderQuantity,orderShipped)
VALUES
('"+DropDownList1.SelectedValue+"','"+lblFile.Text+"','"+lblPrice.Text+"','"+txtQuantity.Text+"','"+DateTime.Now+"')",con);
cmd.ExecuteNonQuery();
con.Close();
lblFinished.Text = "Order has been submitted for process.";
}
WhoAmI is probably right, however your code could be greatly improved to avoid other problems and to also allow you not to allow unhandled exceptions.
I have put extra comments directly in the code:
try
{
// SqlConnection is disposable, so it is recommended to dispose it (using calls Dispose() for you)
using (var con = new SqlConnection(connStr))
{
con.Open();
// this is missing from your code and might the errors actual cause
// SqlCommand is also disposable
using (var cmd = con.CreateCommand())
{
// is is strongly recommended to construct parameterized commands
// to avoid SQL injection (check this - https://technet.microsoft.com/en-us/library/ms161953(v=sql.105).aspx)
cmd.Text = #"
INSERT INTO orders2
(orderName,orderFile,orderType,orderPrice,orderQuantity,orderShipped)
VALUES (#orderName, #orderFile, #orderType, #orderPrice, #orderQuantity, #orderShipped)";
// the parameters - SqlCommand infers parameter type for you
cmd.AddWithValue("#orderName", DropDownList1.SelectedValue);
cmd.AddWithValue("#orderFile", lblFile.Text);
cmd.AddWithValue("#orderType", theMissingParametersForOrderType);
// some conversion might be needed here, as I expect the price to be some number
// with a fixed number of decimals
// e.g. Convert.ToDecimal(lblPrice.Text)
cmd.AddWithValue("#orderPrice", lblPrice.Text);
// same convertion issue as for price
cmd.AddWithValue("#orderQuantity", txtQuantity.Text);
cmd.AddWithValue("#orderShipped", DateTime.Now);
}
}
}
// there are several Exceptions that can be raised and treated separately
// but this at least you can do
catch (Exception exc)
{
// log the error somewhere
// put a breakpoint just below to inspect the full error details
}
// this is executed even if an exception has occurred
finally
{
if (con != null && con.State != ConnectionState.Closed)
con.Close();
}
As a side note, this code belongs to a data layer, no presentation layer. Consider including it within another assembly.
You are inserting 6 values(orderName,orderFile,orderType,orderPrice,orderQuantity,orderShipped) here, but supplied only 5 values. DropDownList1.SelectedValue, lblFile.Text, lblPrice.Text, txtQuantity.Text, DateTime.Now.
Related
I have a standard routine for executing SqlCommand with an exception handler. But if an exception is thrown within this routine then I can't make an rollback if this standard routine is called within a transaction. So how can I check that this standard routine is placed inside a transaction or not? What is the proper way? I have googled a lot so far...
Do I have to thrown a new exception in my exception handler for the standard routine for forcing the overall transaction to rollback?
My standard routine looks like:
try
using (SqlConnection con = new SqlConnection(dbCon))
{
using (SqlCommand cmd = new SqlCommand(SQL, con))
{
con.Open();
cmd.CommandTimeout = 600;
cmd.ExecuteScalar();
}
}
}
catch (Exception ex)
{
// do some stuff here
maybe check for existence in a transaction here
}
My overall transaction look like this:
using (SqlConnection con = new SqlConnection(dbCon))
{
con.Open();
string TransactionName = "TransactionName";
using (SqlTransaction sqlTransaction = con.BeginTransaction(TransactionName))
{
try
{
// do some stuff here and call the standard routine here several times...
}
catch (Exception vDBException)
{
DB.getInstance().RollbackTransaction(sqlTransaction, TransactionName);
}
}
}
I have tried to make use of select ##trancount with no success.
I have also tried to check sys.sysprocesses from SQL Server with no success.
I really hope that someone can show me the right direction.
I am working on a .NET project. In a DAO class (using ADO.NET but this is not important) I have a method like this:
public static List<Inoltro> GetListaInoltriUltimiGiorni(int IdUor, string Protocollista, int NumeroGiorni, DBConnection config)
{
string query = PROT_INOLTRO.INOLTRI_ULTIMI_N_GIORNI_BY_UOR_AND_PROTOCOLLISTA;
List<Inoltro> result = new List<Inoltro>();
using (SqlConnection con = ArxeiaConnection.getARXEIAStringConnection(config.Tenant + "_" + config.Database))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
try
{
cmd.Parameters.AddWithValue("#IdUor", IdUor);
cmd.Parameters.AddWithValue("#Protocollista", Protocollista);
cmd.Parameters.AddWithValue("#NumeroGiorni", NumeroGiorni);
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
// Read advances to the next row.
while (reader.Read())
{
.........................................
.........................................
.........................................
}
}
}
}
catch (Exception ex)
{
con.Close();
throw ex;
}
}
}
return result;
}
As you can see I am creating and returning this object:
List<Inoltro> result = new List<Inoltro>();
The problem is that Visual studio give me the following error on this method signature:
Inconsistent accessibility: return type List<Inoltro> is less accessible than method MyClass.GetListaInoltriUltimiGiorni(....)
Why? What am I missing? How can I fix it?
Your method is public but Inoltro is internal. You cannot have a public method that exposes an internal type. Either make the method internal or the type public.
While we are looking at your code, a few things come to mind.
First, the try catch is unnecessary, since the using already does a Close on the connection if an exception is thrown. Eliminate the try catch.
Second, for your future reference, never say throw ex; in a catch. Say throw; to re-throw an exception. The difference is subtle. throw; re-throws the exact exception that was caught. throw ex; re-throws the exception but resets the stack trace to the current trace, not the original trace.
The only time you want to do throw ex; is when you deliberately want to obscure where an exception came from, for instance, because there is a trust boundary between the current code and the caller. However, in that case it would be better still to throw a new, generic exception.
Third, I don't understand why you have both a while and an if to check to see if the set has rows. Surely if the set is empty then the Read will return false, so there was never a need for the if, right?
Fourth, this is just a style point; normally we would format
using (SqlConnection con = ArxeiaConnection.getARXEIAStringConnection(config.Tenant + "_" + config.Database))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
as
using (SqlConnection con = ArxeiaConnection.getARXEIAStringConnection(config.Tenant + "_" + config.Database))
using (SqlCommand cmd = new SqlCommand(query, con))
{
It is common to have a using whose body is only another using, and in that scenario the unnecessary braces and indentation do not make the code easier to understand.
A fairly large web application written in C# keeps throwing up 2 errors:
'ExecuteReader requires an open and available Connection. The connection's current state is open.'
and
'Invalid attempt to call Read when reader is closed.'
These errors were sporadic -- the pages used to load fine about 95% of the time, but recently they've become endemic, they're occurring all the time and basically crippling the application's functionality.
The web app is highly reliant on an MS SQL database, and the errors appear to not be confined to just one page, but nearly all the pages that connect to the database.
The queries are performed as such:
Database.Open(); // Custom class that has our connection string hard coded.
string query = "SELECT * FROM table"; // (dummy query)
SqlCommand command = new SqlCommand(query, Database.Conn);
SqlDataReader reader = null;
try {
reader = command.ExecuteReader(CommandBehaviour.CloseConnection);
if (reader.HasRows) {
while (reader.Read()) {
// Do something with the data.
}
}
reader.Close();
}
catch (Exception e) {
throw new Exception(e.Message);
}
finally {
if (reader != null) {
reader.Close();
}
}
I've researched these errors on the web and I've seen a few potential solutions that I've tried to no avail:
Putting various parts of the code in a using() block.
Specifying CommandBehaviour.CloseConnection for the reader.
Checking that MARS is enabled.
Ensuring that a new connection object is created each time.
I've spent ages searching for solutions to this, not to mention a long long time trying to make it work, and I'm almost on the verge of pulling my hair out now!
Please help!
EDIT -- Fixed the problem, see the comments section.
It looks to me that Database is a type and not an instance.
You are running into multithreading issues now.
You have 2 options:
Apply the [ThreadStatic] to the field containing the connection object created by Database.Open()
or
Make Database.Open() return a fresh instance of the connection object and use that when constructing the command
In addition to leppie's answer, you should also be Dispose()ing of any IDisposable types:
try
{
Database.Open(); // Custom class that has our connection string hard coded.
string query = "SELECT * FROM table"; // (dummy query)
using (SqlCommand command = new SqlCommand(query, Database.Conn))
using (SqlDataReader reader = command.ExecuteReader(CommandBehaviour.CloseConnection))
{
if (reader.HasRows)
{
while (reader.Read())
{
// Do something with the data.
}
}
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
I have a C# database layer that with static read method that is called every second in background timer.
currently I create SqlCommand, SqlConnection once as a class memeber.
In every method call I execute the command to get the results,I am doing so to avoid creation of connection and command every second, but I am afraid from exception occurs in this method that will break the connection or put the object in the invalid state.
This is my current implementation (Timer Handler)
static void GetBarTime(object state)
{
lock (_staticConnection)
{
SqlDataReader dataReader = null;
try
{
dataReader = _getMaxTimeCommand.ExecuteReader();
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
catch (Exception ex)
{
//Log the error
}
finally
{
dataReader.Dispose();
}
}
}
What is the best practise?
MORE DETAILS:
I am doing this in a timer as there is another prorcess update my table every second, and there is another exposed method used by set of clients and called every second to get the latest value.
So instead of executing select statement every second for each client, I am doing it in a timer and update global variable that is used by the clients.
SqlConnection has pooling built in; you would see almost no difference if you used:
using(SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
// your code
}
each time. And that can react automatically to dead (underlying) connections.
Currently you have a bug, btw; if the command fails, the reader will still be null... either check for null before calling Dispose():
if(dataReader !=null) {dataReader.Dispose();}
or just use using:
try
{
using(SqlDataReader dataReader = _getMaxTimeCommand.ExecuteReader())
{
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
}
catch (Exception ex)
{
//Log the error
}
It can be pretty difficult to find out if an execption means that the connection is a dead duck. To be on the safe side, you could close and reopen the SqlConnection and SqlCommand whenever you encounter an exception, just in case. That doesn't cause any overhead when everything works alright.
I have a very simple Update statement that will update mail server settings and network credentials info... Query works fine when I run it in Access but C# keeps giving me the error stating that my SQL Syntax is wrong ... I have a dataaccess layer (dal class) and Update instance method pasted belows ... But the problem must be sth else cuz I have updated lots of stuff this way but this time it just won't do .. any clues will be greatly appreciated. Thx in advance.
Update instance method in DAL class .. (this is supposed to be a Data Access Layer :) I'm just a management graduate :P
public int UpdateRow(string Query, bool isSP, params OleDbParameter[] args)
{
int affectedRows = -1;
using (con = new OleDbConnection(connStr))
{
using (cmd = con.CreateCommand())
{
cmd.CommandText = Query;
if (isSP)
{
cmd.CommandType = CommandType.StoredProcedure;
}
if (args != null)
{
foreach (OleDbParameter prm in args)
{
cmd.Parameters.Add(prm);
}
}
try
{
con.Open();
affectedRows = cmd.ExecuteNonQuery();
}
catch(OleDbException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
}
}
return affectedRows;
}
And the ASP.NEt codebehind that will do the updating =
protected void Update_Click(object sender, EventArgs e) {
DAL dal = new DAL();
string upt = string.Format("UPDATE [MailConfig] SET Server='{0}', Username='{1}', Password='{2}', AddressFrom='{3}', DisplayName='{4}'",server.Text,username.Text,password.Text,replyto.Text,displayname.Text);
dal.UpdateRow(upt,false,null);
LoadData();
}
peace!
Trying wrapping your field names in [ ]. I have had problems in the past with certain field names such as a username and password and count, etc, being recognized as reserved words and screwing up the sql giving me an error.
First off - don't use string.Format here. Use parameters, and add parameters to the command. Right now, you are wide open to SQL injection attacks. Think "Bobby Tables".
Re "stating that my SQL Syntax is wrong" - can you please quote the exact error?
First of all, you have no where clause in your Update, so it will update all rows, and violate key constraints causing an error, if you have any.
Second, running that kind of code makes you very vunerable to SQL Injection, if someone enters a username that has a sql command embedded in it, you could lose all your data.
You should use parameterized queries. You specify your parameters in the sql command with #paramname instead of using {4}, and then with the command object do accessCommand.parameters.AddWithValue("#paramname", value)
You are using a CommandType of StoredProcedure, but your query is not a stored procedure name, its a sql query without a where clause.
UPDATE [MailConfig]
SET Server='{0}',
Username='{1}',
Password='{2}',
AddressFrom='{3}',
DisplayName='{4}'"
So you need to remove the command type line, or change it to a correct command type CommandType.Text, and add a Where clause specifying what rows are to be affected.
I don't think Access even has Stored Procedures, so there's no using to use that command type with it.
An example of a command that does use stored procedures would be something like:
string sqlCommString = "QCApp.dbo.ColumnSeek";
SqlCommand metaDataComm = new SqlCommand(sqlCommString, sqlConn);
metaDataComm.CommandType = CommandType.StoredProcedure;
The command string for that type is just the name of the stored proc.