I'm trying to write a web application with some database interaction in C#.NET. I'm getting an odd exception that I can't figure out where it's coming from. I found the method that it is coming from and the code is as follows:
protected void cmdDelete_Click(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(#"Server=myname-PC\SQLEXPRESS;Database=dbNames;Trusted_Connection=True;"))
{
try
{
conn.Open();
SqlCommand comm = new SqlCommand("DELETE FROM Names WHERE FirstName=#FirstName AND LastName=#LastName", conn);
char[] delims = new char[1];
delims[0] = ' ';
string[] names = cblNames.SelectedItem.Text.Split(delims);
string fname = names[0];
string lname = names[1];
comm.Parameters.Add(new SqlParameter("#FirstName", fname));
comm.Parameters.Add(new SqlParameter("#LastName", lname));
comm.ExecuteNonQuery();
conn.Close();
cblNames.ClearSelection();
LoadTable();
}
catch (Exception ex)
{
Response.Write("Delete Table: "+ex.Message);
}
}
}
Any help is appreciated!
You will need to look at the line of code that the error is being thrown at and/or simply debug the application. Otherwise, I can only make guesses as to where this could be occurring:
conn.Open(); //conn could be null (if your connection string is bad it would post back a null connection I believe
cblNames.SelectedItem.Text //cblNames could be null (doubtful), but SelectedItem definitely could
LoadTable(); could be throwing it up also
Without more debug information, that is the best answer you are probably going to get.
so is it saying that cblNames.SelectedItem is null, or that the Split function just isn't returning anything?
Well, it's either one or the other and only you have access to the code, so set a break point at that line and when you hit the break point check if SelectedItem is null or if the Text is null. To be exact, we can eliminate the second "option" since Split always returns something, even if it's just an empty array, it still doesn't return null.
Update
Per your comments, it seems that SelectedItem is not being set, so you must track down what is supposed to set SelectedItem and verify that it's doing it correctly.
Looking at your code, cblNames can only be throwing exception. Check stacktrace for specific line of code.
On the other note, it's not recommended to catch the base exception as catch (Exception ex). Always case specific exceptions instead e.g. System.Data.SqlClient.SqlException or System.InvalidOperationException. For more details check MSDN.
The problem that I was having was that I wasn't getting the value on postback because I was leaving this little peace of code out of the page_load function:
If Not IsPostBack()
It was an elementary lapse in knowledge. I have been developing in .NET since this question and I realize how horribly simple it is to make mistakes in a new language. Thank you everyone for dealing with the past noob me.
Related
I tried to find a useful answer to this question, but failed (the closest I found was this). I have a C# app calling a stored procedure which uses SQL TRY/CATCH to handle errors. I can replicate the issue with a sample stored procedure like this:
if object_id('dbo.TestSQLError') is not null drop proc dbo.TestSQLError
go
create proc dbo.TestSQLError
as
begin try
select 1 / 0
end try
begin catch
raiserror('Bad tings appen mon', 16, 1)
end catch
then a little dummy program like this:
namespace TestSQLError
{
class Program
{
public const string CONNECTION_STRING = #"data source=localhost\koala; initial catalog=test; integrated security=true;";
static void Main(string[] args)
{
try
{
using (SqlConnection conn = new SqlConnection(CONNECTION_STRING))
{
SqlCommand cmd = new SqlCommand("dbo.TestSQLError", conn) { CommandType = System.Data.CommandType.StoredProcedure };
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine(rdr.GetValue(0).ToString());
}
rdr.Close();
}
conn.Close();
}
Console.WriteLine("Everything looks good...");
}
catch (SqlException se)
{
Console.WriteLine("SQL Error: " + se.Message);
throw se;
}
catch (Exception e)
{
Console.WriteLine("Normal Error: " + e.Message);
throw e;
}
Console.ReadLine();
}
}
}
The stored procedure raises an error of level 16 which as far as I've read should be enough to be error-worthy. However control never jumps to the catch block; it just chugs through like nothing went wrong.
I read someone suggest using OUTPUT parameters... which I can do, but it seems like I must be missing something fundamental and simple here. Can anyone help?
UPDATE: It would appear if I use ExecuteNonQuery() the errors propagate just fine. However my use case is a procedure which performs DML and returns data based on that DML. Maybe the answer is "don't do that" but it'd be nice to know if there's a way to simply catch an error when grabbing results.
The reason is because the raise error is after the end of the first result set in the data reader and we’ll only get the error if we call NextResult() on the data reader!
When using a SqlDataReader it will only iterate over the first result
set, which in this case will be the select in the stored procedure
Try and see more details here
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (!rdr.IsClosed())
{
while (rdr.Read())
{
Console.WriteLine(rdr.GetValue(0).ToString());
}
if (!rdr.NextResult())
{
rdr.Close();
}
}
}
I can make three suggestions:
Use CommandType.Text instead of CommandType.StoredProcedure. This may be fixed now, but a number of years ago I found that CommandType.StoredProcedure would always buffer message outputs into batches of about 50, while CommandType.Text would allow the messages to come back to C# right away.
Add a WITH NOWAIT hint to your RAISERROR code.
Don't forget about the FireInfoMessageEventOnUserErrors property. You do want to handle the InfoMessage event.
I'm not sure any of these will solve your problem, but they should give you some direction.
No exceptions, everything gets executed but the update doesn't happen!
Everything works ok when I have just #JIR parameter but now I added #Paragon and the update doesn't do it's job. No exception whatsoever data passed is OK...
I don't see anything wrong with this query does anyone know what could possibly be going wrong?
private static void InsertJIR(FisDnevni racun)
{
using (OleDbConnection con = new OleDbConnection(RegistarBlagajna.Modul.VezaNaBazu.ConnectionString))
{
try
{
con.Open();
OleDbCommand cmd = new OleDbCommand(#"
UPDATE FisDnevni
SET [JIR] = #JIR,
[Paragon] = #Paragon
WHERE BrojRacuna = #BrojRacuna"
, con);
cmd.Parameters.AddWithValue("#JIR", racun.JIR.Substring(0,37));
cmd.Parameters.AddWithValue("#BrojRacuna", racun.BrojRacuna);
cmd.Parameters.AddWithValue("#Paragon", racun.Paragon);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception)
{
throw;
}
}
}
This is a good old problem - ensure the query parameters in OleDbParameter are declared in proper order like this:
using (OleDbConnection con = new OleDbConnection(RegistarBlagajna.Modul.VezaNaBazu.ConnectionString))
{
try
{
con.Open();
using (OleDbCommand cmd = new OleDbCommand(#"UPDATE FisDnevni SET [JIR] = #JIR, [Paragon] = #Paragon WHERE BrojRacuna = #BrojRacuna", con)
{
cmd.Parameters.AddWithValue("#JIR", racun.JIR.Substring(0,37));
// this must be the second parameter instead of third one
cmd.Parameters.AddWithValue("#Paragon", racun.Paragon);
cmd.Parameters.AddWithValue("#BrojRacuna", racun.BrojRacuna);
cmd.ExecuteNonQuery();
con.Close();
}
}
catch (Exception)
{
throw;
}
}
Note that OLE DB .NET Provider doesn't recognize named parameters for OleDbCommand when CommandType is set to Text, but it apparently does recognize the parameter order, hence as long as they're passed in proper order, it'll accepted as query parameter.
Related issue:
how to update a table using oledb parameters?
maybe i've just never used it, but why is there an # here?
OleDbCommand(#"
i also havent worked with C# in a while but is multi-line concatenation possible without a + or something?
thirdly why are you using [] on these column names? i don't see any special characters or spaces.
this post is sounding a lot more dikkish than i mean it to be, im not trying, just legit curious
I have a trouble with my coding. This is a source code what I coding for this program.
OracleConnection kon;
public Form2()
{
InitializeComponent();
FillCombo();
}
void FillCombo()
{
OracleConnection kon = Koneksi.getKoneksi();
OracleCommand cmd;
try
{
kon.Open();
cmd = new OracleCommand();
cmd.Connection = kon;
cmd.CommandText = "SELECT * FROM JOBS";
OracleDataReader reader = cmd.ExecuteReader();
comboBox1.Items.Add(reader.GetString(reader.GetOrdinal("JOB_ID")));
}
catch (Exception ex)
{
MessageBox.Show("Data has been failed to show: " + ex.Message);
}
finally
{
kon.Close();
kon.Dispose();
}
}
}
}
When I running this program, system will show dialog "operation is not valid due to the current state of the object".
When I running the Program
There's No Error
How to solve this error? I'll bind data to comboBox from database. I mean, I want to add JOB_ID to combo Box such as AD_VP, HR_REP, etc btw.
Btw, I'm sorry if my English is poor.
One obvious thing that's missing is that you didn't call reader.Read() before attempting to read from your data reader. When you call OracleDataReader reader = cmd.ExecuteReader();, at that moment, the data reader is positioned before the first record. You need to call reader.Read() to move it to the first record. This can easily explain the error you got.
OracleDataReader reader = cmd.ExecuteReader();
reader.Read(); // Add this. Check for a return value of false if necessary.
comboBox1.Items.Add(reader.GetString(reader.GetOrdinal("JOB_ID")));
Apart from that, it would also be a good idea to dispose of the data reader properly. You may want to use a using block for this.
So what youa re trying to do is Adding the ordial number of the JOB_ID column to a combobox. As you probably know GetOrdinal returns in int.
Why don't you just go like this:
...
comboBox1.Items.Add(Convert.ToString(reader.GetOrdinal("JOB_ID")));
...
Earlier I posted this code but it was much more messy, parts were commented out, and I was using concatenation to INSERT to the database. I was told to clean it up, challenged to use parameters, and ask more concise questions. With that being said, the connection to the database was given to me with mostly pseudo-code with some direct commands.
1) Is my Try-Catch set up correctly?
2) "server = LOCALHOST" is underlined in red, it says it can't convert 'string' to System.Data.SqlClient.SqlConnection'
3) "Database" and "Lab1" are underlined saying it doesn't exist in current context? What does this mean?
4) "Trusted_connection" and "yes" have the same error message as #3.
5) I'm not sure what to put after "cmd.Connection = " which is why it's commented out and has a question mark after it.
6) Is my varname1.Close(); in the right spot? I feel like it makes sense for it to actually go between the last 2 closing brackets?
7) In the Catch "SqlException" is underlined and the error says "The type or namespace SqlException could not be found". I found a try-catch from another user on stackoverflow that asked the question and someone responded with the catch set up like that so I copied it.
8) I'm trying to figure out parameters, Is mine set up correctly? All I have is 1 textbox in which the user inputs data and it enters into an array. "Name" is the name of the attribute of the student in the database, and I just made up #Name as a variable? I found a parameter example from another user also on stackoverflow and kind of made match mine.
public static int counter = 0;
protected void btnDisplay_Click(object sender, EventArgs e)
{
try
{
System.Data.SqlClient.SqlConnection varname1 = new System.Data.SqlClient.SqlConnection();
varname1 = "server = LOCALHOST";
Database = Lab1;
Trusted_connection = yes;
varname1.Open();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
// cmd.Connection = (?)
cmd.CommandText = "Delete From Student";
cmd.ExecuteNonQuery();
for(int i=0; counter >= i; i++)
{
cmd.CommandText = "INSERT INTO Lines (Name) " + "VALUES (#Name)";
cmd.Parameters.AddWithValue("#Name", studentList[i]);
counter++;
}
varname1.Close();
}
catch (SqlException ex)
{
lbl5.Text = "Connection could not be established";
}
}
You need to find a good resource (or a few) and learn how to make proper database calls. Here's one. Here's another, on creating connection strings.
I haven't tested the following, but something like this should work.
using (var conn = new System.Data.SqlClient.SqlConnection("Server=LOCALHOSTDatabase=Lab1;Trusted_Connection=True;"))
{
conn.Open();
using (var cmd = new SqlCommand("Delete From Student", conn))
{
cmd.ExecuteNonQuery();
}
using (var cmd = new SqlCommand("INSERT INTO Lines (Name) VALUES (#Name)", conn))
{
for (int i = 0; counter >= i; i++)
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#Name", studentList[i]);
cmd.ExecuteNonQuery();
}
counter++;
}
}
As for some of your other questions...
#1 - Your try/catch is setup okay.
#6 - Don't bother calling Close() - use a using block
#7 - The exception name looks okay. Do you have using System.Data.SqlClient; at the top of your form? You may be getting an error here because of other lines of code with errors... hard to say.
#8 - That looks fine.
You should have a finally block with your try-catch
Your SQLConnection should be created with the connection string as a parameter. You can't set it equal to a String, it's a SQLConnection.
I don't know where Database and Lab1 are declared but it's obviously not within the scope of your function.
See 3. And yes has no meaning.
cmd.Connection = varName1
You should close your connection in a finally block to ensure it is closed even if an exception is thrown
Have you imported System.Data.SQLClient?
Adding parameters with values will replace #Name in your SQL string with the value you supplied
So what i am looking to do is use a web service call to implement an oracle procedure. To be more specific: I what it so that when i put a value into a parameter in my web service and run it, i want that to be the value sent to the procedure in oracle and then after successfully running to return to the web service as true.
What i have currently tried to to is this:
public bool InsertMachineModels(string MachineModel)
{
logger.DebugFormat("FilteredReportInputsDAO.InsertMachineModel({0})", MachineModel);
bool retVal = true;
using (OracleConnection conn = new OracleConnection(connectionString))
{
using (OracleCommand cmd = new OracleCommand("Admin_Utilities.InsertMachineModel", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("pMachineModel", OracleType.Cursor).Value = Convert.ToString(MachineModel);
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
if (IsErrorLogging)
logger.Error("FilteredReportInputsDAO.InsertMachineModels() Exception: ", ex);
retVal = false;
}
finally
{
conn.Close();
}
}
}
return retVal;
}
Below you will find my procedure which runs correctly when implemented in sql developer.
procedure InsertMachineModel( pMachineModel in nvarchar2)
is
begin
insert into machine_models (Machine_model) values (pMachineModel);
commit;
Exception when others then
pb_util.logdata(1, 'Admin_utilities.InsertMachineModel', 'Exception thrown', sqlerrm || ' stack ' || dbms_utility.format_error_backtrace);
rollback;
raise;
end;
What i believe to be the problem is this line in the web service:
cmd.Parameters.Add("pMachineModel", OracleType.Cursor).Value = Convert.ToString(MachineModel);
In my logger it says that a cursor must be implemented as a parameterdirection.output parameter however i do not believe in that case you can take a value and send it to the api, but if i am wrong feel free to correct me.
So i guess my question is: If what i believe to be correct in the statement above about parameterdirection is wrong, what is the correct answer?
Can anyone give me any suggestions as to how to implement what i am attempting to do correctly?
Any help or suggestions are greatly appreciated. Thank you.
I think your problem is in this line:
cmd.Parameters.Add("pMachineModel", OracleType.Cursor).Value =
Convert.ToString(MachineModel);
You're attempting to add a parameter of type OracleType.Cursor, which isn't correct or necessary. Try changing the line to this:
cmd.Parameters.Add("pMachineModel", OracleType.Char).Value = MachineModel;
(There's also no need for Convert.ToString here - MachineModel is already a String).