OracleDataAdapter hangs on Fill method in Windows XP.
While debugging In windows 7 works fine but VS2008 hangs on Windows XP.
The same applies to the release versions of the app. The sql query used has nothing to do, I have tested the function using simple queries and they all fail.
Here is a code snippet illustrating the initial code:
public static string DBSelectString(string ssql)
{
try
{
OracleDataAdapter da = new OracleDataAdapter();
DataTable dt = new DataTable();
da.SelectCommand = new OracleCommand(ssql, Connection);
da.Fill(dt);
return dt.Rows[0].ItemArray[0].ToString();
}
catch (Exception ex)
{
Utils.Log(ex.Message);
return string.Empty;
}
}
Using OracleDataReader still hangs but I managed to find a workaround.
public static string DBSelectStringDR(string ssql)
{
OracleDataReader reader = null;
try
{
Connection.Open();
OracleCommand command = new OracleCommand(ssql, Connection);
reader = command.ExecuteReader();
if (reader.HasRows)
{
//reader.Read();
//return reader.GetValue(0).ToString(); <-------- normally hangs here
try
{
//workaround:
//force exception, since Read has not been executed
string test = reader.GetValue(0).ToString();
}
catch { }
// then, everything works fine
reader.Read();
return reader.GetValue(0).ToString();
}
else
{
return string.Empty;
}
}
catch (Exception ex)
{
Utils.Log(ex.Message);
return string.Empty;
}
finally
{
if (reader != null) reader.Close();
Connection.Close();
}
}
Any ideas ?
Related
I have this query in my c# asp.net server. When I run it on the server it output the inserted status and not the deleted one as expected. when I run the same query on the Microsoft management SQL studio it works just fine.
Any suggestions for what could be wrong?
public override BaseMessageStatus SetHubMessageStatus(Participant toParticipant, Transaction transaction, Ticket ticket, BaseMessageStatus nextStatus)
{
BaseMessageStatus originalStatus = BaseMessageStatus.Undefined;
SqlConnection sqlConnecntion = SQL_CONNECTION;
string stquery = #"update [webMessages] set [status]=#status OUTPUT Deleted.status
where [sessionId]=#sessionId and [transactionId]=#transactionId and [toPartID]=#toParticipantID";
//new DataTable
DataTable dt = new DataTable();
using (sqlConnecntion)
{
using (SqlCommand cmd = new SqlCommand(stquery))
{
cmd.Connection = sqlConnecntion;
cmd.Parameters.AddWithValue("#sessionId", ticket.id);
cmd.Parameters.AddWithValue("#transactionId", transaction.id);
cmd.Parameters.AddWithValue("#toParticipantID", toParticipant.id);
cmd.Parameters.AddWithValue("#status", (int)nextStatus);
try
{
sqlConnecntion.Open();
cmd.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(dt);
if (dt != null && dt.Rows.Count > 0)
{
if (dt.Rows[0]["status"] != null && dt.Rows[0]["status"] != DBNull.Value)
{
Enum.TryParse<BaseMessageStatus>(dt.Rows[0]["status"].ToString(), out originalStatus);
}
}
sqlConnecntion.Close();
}
catch (Exception ex)
{
Logger.Error(ex);
}
}
}
return originalStatus;
}
Ok - I have finally got my connection string and sql string correct in this WPF form. I kept getting reader exceptions until I finally got the sql string the correct way, so since I am not getting errors now - I am assuming it is correct. Have inserted a breakpoint at IDbCommand and stepped through, and all steps seem to go fine. But the program locks up and does not display any data in the datagrid. Cannot even click on the form once all statements are processed. What have I missed here?
This is a Progress OpenEdge DB - and this is the recommended connection and command from Progress.
private void MonReadButton_Click(object sender, RoutedEventArgs e)
{
var estNum = EstTextBox.Text;
{
string connectString = "DSN=****;uid=**;pwd=*****;host=****;port=****;db=****;";
using (OdbcConnection dbConn = new OdbcConnection(connectString))
{
try
{
dbConn.Open();
}
catch (Exception)
{
MessageBox.Show("connection failed");
}
IDbCommand dbcmd = dbConn.CreateCommand();
string sqlstr = #"SELECT ""Estimate"".""Labor-Cost"" FROM ""GAMS1"".""PUB"".""Estimate"" WHERE ""Estimate"".""Estimate-ID""=" + estNum;
dbcmd.CommandText = sqlstr;
IDataReader reader = dbcmd.ExecuteReader();
while (reader.Read())
{
DataTable dt = new DataTable();
dt.Load(reader);
DataGrid1.ItemsSource = dt.DefaultView;
}
reader.Close();
reader = null;
dbcmd.Dispose();
dbcmd = null;
dbConn.Close();
}
}
}
I am using the Oracle Data Provider for .NET version 4.112.3.0 to access an Oracle 9 database from an ASP.NET web application. Even though I explicitly Close and Dispose of the OracleDataReader and OracleConnection objects, I receive an ORA-01000 maximum open cursors exceeded error at times.
Most of my ODP.NET code is wrapped into a custom class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Data;
namespace MyNamespace
{
public class MyOracleClass : IDisposable
{
private static string connectionString = "Data Source=myDB;Persist Security Info=True;User ID=myUser;Password=myPassword;";
private OracleConnection _conn;
private OracleTransaction _txn;
public MyOracleClass()
{
try
{
_conn = new OracleConnection(connectionString);
if (_conn.State != ConnectionState.Open)
_conn.Open();
_txn = _conn.BeginTransaction(IsolationLevel.ReadCommitted);
}
catch (Exception ex)
{
// Log Exception
throw ex;
}
}
public void Query(string query, ref OracleDataReader dr)
{
dr = null;
OracleCommand cmd = null;
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
cmd = new OracleCommand(query, _conn);
dr = cmd.ExecuteReader();
}
catch (Exception ex)
{
// Log Exception
throw ex;
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
public void Disconnect()
{
try
{
if (IsConnectionOpen())
{
_txn.Rollback();
_conn.Close();
}
}
catch (Exception ex)
{
// Log Exception
}
}
public void Dispose()
{
Disconnect();
try
{
if (this._txn != null)
{
_txn.Dispose();
_txn = null;
}
}
catch (Exception ex)
{
// Log Exception
}
try
{
if (this._conn != null)
{
this._conn.Dispose();
}
}
catch (Exception ex)
{
// Log Exception
}
}
public bool IsConnectionOpen()
{
if (this._conn.State == ConnectionState.Open)
{
return true;
}
return false;
}
}
}
I then use the class in my program.
public void test()
{
OracleDataReader dr = null;
MyOracleClass oracleDb = null;
string query = "SELECT COL_1, COL_2, COL_3 FROM MY_TABLE";
try
{
oracleDb = new MyOracleClass();
oracleDb.Query(query, ref dr);
if(!dr.HasRows)
{
// No data found
}
else
{
while(dr.Read())
{
// Process data
}
}
}
catch(Exception ex)
{
// Log Exception
}
finally
{
if(dr != null)
{
dr.Close();
dr.Dispose();
}
oracleDb.Dispose();
}
}
My query returns an average of 500 rows. When I first experienced the issue, I decided to go to the database to see how many cursors were actually opening up. The OPEN_CURSORS parameter for my database is set to 100. For a given call to the query, I noticed there were 92 open cursors for this simple select query and would break the 100 cursor limit at times! Why would such a large number of cursors open when using the OracleDataReader?
Note, I've been testing this on a development system running Windows Server 2012 with IIS 8.0. I've also called the OracleConnection.ClearAllPools method once finished with the OracleConnection, but this didn't seem to help either. I also tested the query by populating a DataTable object by using the Fill method along with an OracleDataAdapter. Using this method only opened 3 cursors. Why is there such a variation in the number of cursors opened?
I am developing a banking application in which I have written a helper class.
What happens is whenever I continuously, 5 to 7 or more times, press the refresh button, it gives me this error: Fill: SelectCommand.Connection property has not been initialized.
Can any body specify what I am missing in my code, or what more could I do to make it better to perform without any error?
My helper class function is :
private static OdbcCommand cmd;
private static OdbcDataAdapter da;
private static DataTable dt;
public static void GetDataInDataGrid(string sp_Name, GridView gv)
{
dt = new DataTable();
try
{
using (cmd = new OdbcCommand(sp_Name))
{
cmd.Connection = Connection.ConnString.ConnectionString;
using (da = new OdbcDataAdapter(cmd))
{
da.Fill(dt);
if (dt.Rows.Count > 0)
{
gv.DataSource = dt;
gv.DataBind();
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
The error is occurring in the below code, at the throw statement
try
{
if (!IsPostBack)
{
herlperUtility.GetDataInDataGrid("{ CALL asp_sp_GetDataForSupervisor }", this.gvSuperviseDataGrid);
if (this.gvSuperviseDataGrid.DataSource == null)
{
this.divFailure.InnerText = "No Records Found!!!";
this.divFailure.Attributes.Add("style", "display:block;margin-top:20px;");
}
}
}
catch (Exception ex)
{
throw ex;
}
Write
using (cmd = new OdbcCommand(sp_Name,Connection.ConnString.ConnectionString))
inplace of
using (cmd = new OdbcCommand(sp_Name))
{
cmd.Connection = Connection.ConnString.ConnectionString;
I have a problem with my SQL datareader, i want to make an external class and make the code in my xaml.cs as short as possible, because there are a lot of sqldatareaders needed in my program. for this I want to pass following two strings to the datareader class:
public void refreshcombobox()
{
cbGebruiker.Items.Clear();
database = new DataBase();
string sqlrdr = "(rdr.GetString(1).ToString().Trim())";
List<string> reader = database.ReaderRdr("Select * from Gebruikers", ref sqlrdr);
foreach (String str in reader)
{
cbGebruiker.Items.Add(str);
}
}
however, when I do this this is the result in my program instead of the actual results that are stored in the database:
http://i58.tinypic.com/301j2vo.jpg (I can't post images)
can somebody help me with this? I've searched everywhere...
I don't know how to pass the rdr.GetString(1).ToString().Trim() to make it actually look stuff up in the db. Instead of just copying the string directly into the list.
This is the class:
namespace ClassLib
{
public class DataBase
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["kassadatabase"].ConnectionString);
public object ScalarObject(string sql)
{
object value = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
value = cmd.ExecuteScalar();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (conn != null) conn.Close();
}
return value;
}
public List<string> ReaderRdr(string sql)
{
SqlDataReader rdr = null;
List<string> reader = new List<string>();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
//reader.Add(rdr.GetString(1).ToString().Trim());
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (rdr != null) rdr.Close();
if (conn != null) conn.Close();
}
return reader;
}
//public List<string> ReaderRdr(string sql, ref string str)
//{
// SqlDataReader rdr = null;
// List<string> reader = new List<string>();
// try
// {
// conn.Open();
// SqlCommand cmd = new SqlCommand(sql, conn);
// rdr = cmd.ExecuteReader();
// while (rdr.Read())
// {
// //MessageBox.Show(str.ToString());
// //var strRdr = str;
// //MessageBox.Show(strRdr.ToString());
// //reader.Add(rdr.GetString(1).ToString().Trim());
// reader.Add(str);
// Console.WriteLine(String.Format("{0}", rdr[0]));
// }
// }
// catch (SqlException ex)
// {
// MessageBox.Show(ex.Message);
// }
// finally
// {
// if (rdr != null) rdr.Close();
// if (conn != null) conn.Close();
// }
// return reader;
//}
public void ExecuteNQuery(string insertString)
{
try
{
conn.Open();
SqlCommand cmd2 = new SqlCommand(insertString, conn);
cmd2.ExecuteNonQuery();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (conn != null) conn.Close();
}
}
}
}
public List<string> ReaderRdr(string sql)
{
SqlDataReader rdr = null;
List<string> reader = new List<string>();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
//reader.Add(rdr.GetString(1).ToString().Trim());
}
.....
now in the methode public list i want to replace the //reader.Add(rdr.GetString(1).ToString().Trim()); part(wich works fine)
with a string that is passed to the method.
public List<string> ReaderRdr(string sql, string strRdr)
{
SqlDataReader rdr = null;
List<string> reader = new List<string>();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
//reader.Add(strRdr);
}
I'm not 100% sure what you're trying to do, but I can tell you right now that this is what you're doing wrong - the string (str) you're passing to ReaderRdr is just a string literal of C# code. There's super hacky (super inadvisable) things you can do to mimic what exists in other languages as eval(), but there's no built-in way to do that in C#. Nothing (sensible) you do to "(rdr.GetString(1).ToString().Trim())" is ever going to get a string, or cast it to string, or trim anything.
Within your ReaderRdr function, all you're accomplishing is just to add the string str to your List<string> reader. This accomplishes nothing and has no bearing whatsoever on the results you get from your database query in your SqlDataReader rdr. If you want to store the data you actually get from your database, use rdr, not the (useless) string argument str.
Also, I feel like you must have left something out of your code - you're instantiating your SqlCommand cmd with conn as your second argument, but I don't see that defined anywhere within your ReaderRdr method, and it's not an argument passed to ReaderRdr. You don't have an SqlConnection object as a field or property within your class, do you?
As far as what you should maybe do, despite lacking much of any context in terms of your actual aims - if you want to get any given column of the result for each row returned by your SqlDataReader:
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
var yourDataCell = rdr[yourColumnIndex];
// or:
var yourDataCellOtherWay = rdr["YourColumnName"];
}
Alternately, you can just iterate through each of the cells in any given row produced by your SqlDataReader like so:
for(int i = 0 ; i < numberOfColumns; i++) {
// do something with rdr[i] here
}
I'm not sure if there's anything you can do establish numberOfColumns based on the state of your SqlDataReader, but others might know better.
You actually adding the String that you passed to a function to your reader reader.Add(str); You get the response from SQL I your rdr.
This item will show you something from your database:
Console.WriteLine(String.Format("{0}", rdr[0]));