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.
Related
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
I'm trying create a class in C# for manipulate Mysql data
I can get datas with my methods but I can't update data, and no return nothing exceptions
I using this line for call my method
Email1.Text=bdOp.alterContent(Email1.Text, "Email");
Method 'alterContent':
public String alterContent(String valor, String nome)
{
String query = "update conteudo set conteudo = #valor where nome= #nome ";
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#valor", valor);
cmd.Parameters.AddWithValue("#nome", nome);
try
{
conn.Open();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
conn.Close();
return "Sucesso.";
}
catch (Exception erro) { return erro.ToString(); }
}
This method has return String, because I had using to check exceptions
I don't know why this code no update my data and no return any exceptions
I had a very similar situation last night... it was in MVC, so I had to stop the virtual localhost, and do a clean build. After restarting visual studio... it worked. I wasn't getting any error either.
Also, validate the text in Email.Text, perhaps something there might be triggering a problem.
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).