Ado.net OracleCommand does not throw timeout exception (executing stored procedure) - c#

I am executing a ORACLE Stored procedure using System.OracleClient.OracleCommand and set CommandTimeout = 5; (for example)
But I want to set a timeout such that if the command object execution takes more than say 5 minutes it should get aborted (getting exception...OracleException) so that I can show an error message to the user. Let me know how can this be done. This is my written code example.
try
{
_dbConnectionString.Open();
var cmdOracle = new OracleCommand("hfghgh", _dbConnectionString)
{
CommandType = CommandType.StoredProcedure
};
OracleCommandBuilder.DeriveParameters(cmdOracle);
cmdOracle.Parameters["inputParam"].Value = 1;
tran =_dbConnectionString.BeginTransaction(IsolationLevel.ReadCommitted);
cmdOracle.Transaction = tran;
cmdOracle.CommandTimeout = 5;
await cmdOracle.ExecuteNonQueryAsync();
tran.Commit();
return res = cmdOracle.Parameters["outputParam"].Value.ToString();
}
catch (OracleException ex)
{
dynamic exOra = ex;
int errorNo = exOra.Number;
if (errorNo == 01013)
{
throw new ResponseFailException(ex);
}
else
{
throw ex;
}
}

Related

I am getting the error System.InvalidOperationException: 'Invalid operation given the current state of the object.'

When the code is working and it reaches the part where it performs a Commit, it is where the error appears
I have seen solutions where a modification must be made to the Webconfig in the appsettings section, however, is there no other solution that does not have to do with modifying the Webconfig?
This is the code where the error appears, exactly in the Commit
public ErrorCode insertNC(EntidadesNC data)
{
var errorCode = new ErrorCode();
DbConnection DataConnection = ConnectionGet(enuTypeDataBase.OracleVTime);
DbTransaction tran = null;
try
{
DataConnection.Open();
tran = DataConnection.BeginTransaction();
foreach (var item in data.ListainsertNC)
{
if (errorCode.P_COD_ERR == 0)
{
errorCode = insertNCV2(item, DataConnection, tran);
}
}
}
catch (Exception ex)
{
errorCode.P_COD_ERR = 1;
errorCode.P_MESSAGE = ex.ToString();
ELog.save(this, ex.ToString());
}
finally
{
if (errorCode.P_COD_ERR == 0)
{
tran.Commit();
}
else
{
tran.Rollback();
}
if (DataConnection.State == ConnectionState.Open) DataConnection.Close();
}
return errorCode;
}
This is the code where the function insertNCV2 is called
public ErrorCode insertNCV2(itemNC data, DbConnection connection, DbTransaction tran)
{
List<OracleParameter> parameter = new List<OracleParameter>();
var response = new itemNC();
var errorCode = new ErrorCode();
var sPackageName = ProcedureName.pkg_paymentNC + ".SP_PRUEBA_PAYROLL";
try
{
parameter.Add(new OracleParameter("P_NID_COTIZACION", OracleDbType.Int64, data.P_NID_COTIZACION, ParameterDirection.Input));
parameter.Add(new OracleParameter("P_NRECEIPT", OracleDbType.Varchar2, data.P_NRECEIPT, ParameterDirection.Input));
parameter.Add(new OracleParameter("P_SCODCHANNEL", OracleDbType.Int64, data.P_SCODCHANNEL, ParameterDirection.Input));
//OUTPUT
OracleParameter P_COD_ERR = new OracleParameter("P_COD_ERR", OracleDbType.Int32, 9000, errorCode.P_COD_ERR, ParameterDirection.Output);
OracleParameter P_MESSAGE = new OracleParameter("P_MESSAGE", OracleDbType.Varchar2, 900, errorCode.P_MESSAGE, ParameterDirection.Output);
parameter.Add(P_COD_ERR);
parameter.Add(P_MESSAGE);
OracleDataReader odr = (OracleDataReader)this.ExecuteByStoredProcedureVT(sPackageName, parameter);
// ELog.CloseConnection(odr);
}
catch (Exception ex)
{
errorCode.P_COD_ERR = 1;
errorCode.P_MESSAGE = "Hubo un error al insertar los sub items de las coberturas"; // ex.ToString();
ELog.save(this, ex.ToString());
}
return errorCode;
}
I am thankful for any kind of help :)
InvalidOperationException with database operations generally indicates that the connection has been closed or aborted before your line of code executes.
The other scenario with transactions is if the transaction was never started. With Transactions things are a bit easier, we don't need to rollback a transaction on an exception, many exceptions raised during DB operations will abort the transaction anyway, closing the connection without an explicit Commit will also effectively rollback the transaction.
Use Rollback to revert back to a transaction check point, not to cancel or abort the transaction.
Moving the commit logic might help you to debug this:
public ErrorCode insertNC(EntidadesNC data)
{
var errorCode = new ErrorCode();
DbConnection DataConnection = ConnectionGet(enuTypeDataBase.OracleVTime);
DbTransaction tran = null;
try
{
DataConnection.Open();
tran = DataConnection.BeginTransaction();
foreach (var item in data.ListainsertNC)
{
if (errorCode.P_COD_ERR == 0)
{
errorCode = insertNCV2(item, DataConnection, tran);
}
}
if (errorCode.P_COD_ERR == 0)
{
tran.Commit();
}
else
{
tran.Rollback();
}
}
catch (Exception ex)
{
errorCode.P_COD_ERR = 1;
errorCode.P_MESSAGE = ex.ToString();
ELog.save(this, ex.ToString());
}
finally
{
if (DataConnection.State == ConnectionState.Open) DataConnection.Close();
}
return errorCode;
}

.Net Core Transaction Another Dll

lib.ParamsInsert is called via another dll.
The transaction is rolled back when there is a problem with the throw statement. However, the operations in paramsInsert can not be undone.
In lib.ParamsInsert, there is a transaction in its own error.
spcarikart.Repository lib = new spcarikart.Repository();
using (var transaction = db.Database.BeginTransaction())
{
try
{
var result = db.Acenta.Add(obj).Entity;
var a = lib.ParamsInsert(db, new Params
{
Baslik = "Bahdir",
Deger = "1"
});
// ....Maybe Error other process
db.SaveChanges();
return result;
}
catch (Exception ex)
{
transaction.Rollback();
}
}
ParamsInsert
using (var transaction = db.Database.BeginTransaction())
{
try
{
var resul = db.Params.Add(obj).Entity;
db.SaveChanges();
transaction.Commit();
return resul;
}
catch (Exception ex)
{
transaction.Rollback();
throw new Exception();
}
}
They use different transactions. Don't start new transaction, as I see, you work with the same db context, so needn't start transaction in paramsInsert, remove using (var transaction = db.Database.BeginTransaction()) from it.

My application in ASP.NET sometimes identifies procedures of postgresql and sometimes shows error "this procedure does not exist"

I have an application currently fully operational using OracleDB.Recently, I converted my OracleDB into PostgreSQL and I am facing a weird problem.Whenever I try to access my procedure of PostGreSQL through application, sometimes it works perfectly and sometimes does not.It gives an error saying that "this procedure(my procedure name) does not exist,while it exists in the database and works perfectly with pgAdmin query tool. I am really confused,please help me out. Here I am giving one of my sample procedure below and attaching error log too.
CREATE OR REPLACE FUNCTION sylvia.pro_occupation_add(
p_occupationid bigint,
p_occupationname text,
p_occupationdetails text)
RETURNS void
LANGUAGE 'plpgsql'
AS $BODY$
begin
insert into sylvia.occupation (occupationid,occupationname,occupationdetails)
values (p_occupationid, p_occupationname, p_occupationdetails);
end;
$BODY$;
C# code :
private DataSet _createOccupation(DataSet inputDS)
{
ErrorDS errDS = new ErrorDS();
EmployeeHistDS employeeHistDS = new EmployeeHistDS();
DBConnectionDS connDS = new DBConnectionDS();
//extract dbconnection
connDS.Merge(inputDS.Tables[connDS.DBConnections.TableName], false, MissingSchemaAction.Error);
connDS.AcceptChanges();
//create command
NpgsqlCommand cmd = new NpgsqlCommand();
cmd.CommandText = "PRO_OCCUPATION_ADD";
cmd.CommandType = CommandType.StoredProcedure;
employeeHistDS.Merge(inputDS.Tables[employeeHistDS.Occupation.TableName], false, MissingSchemaAction.Error);
employeeHistDS.AcceptChanges();
foreach (EmployeeHistDS.OccupationRow row in employeeHistDS.Occupation)
{
long genPK = IDGenerator.GetNextGenericPK();
if (genPK == -1)
{
return UtilDL.GetDBOperationFailed();
}
cmd.Parameters.Add("p_OccupationId", genPK);
cmd.Parameters.Add("p_OccupationName", row.OccupationName);
if (!row.IsOccupationDetailsNull()) cmd.Parameters.Add("p_OccupationDetails", row.OccupationDetails);
else cmd.Parameters.Add("p_OccupationDetails", DBNull.Value);
bool bError = false;
int nRowAffected = -1;
nRowAffected = ADOController.Instance.ExecuteNonQuery(cmd, connDS.DBConnections[0].ConnectionID, ref bError);
if (bError == true)
{
ErrorDS.Error err = errDS.Errors.NewError();
err.ErrorCode = ErrorCode.ERR_DB_OPERATION_FAILED.ToString();
err.ErrorTier = ErrorTier.ERR_TIER_DL.ToString();
err.ErrorLevel = ErrorLevel.ERR_LEVEL_SEVER.ToString();
err.ErrorInfo1 = ActionID.ACTION_OCCUPATION_ADD.ToString();
errDS.Errors.AddError(err);
errDS.AcceptChanges();
return errDS;
}
}
errDS.Clear();
errDS.AcceptChanges();
return errDS;
}
public int ExecuteNonQuery(NpgsqlCommand cmdInsertUpdateDelete, int connectionID, ref bool bError)
{
CConnectionInfo connInfo = (CConnectionInfo)this.m_hashConn[connectionID];
if (connInfo == null)
{
AppLogger.LogWarning("Connection ID '" + connectionID + "' does not exist in connection pool.\nCould not execute ExecuteNonQuery method.");
bError = true;
return -1;
}
NpgsqlConnection conn = connInfo.m_Conn_PG;
NpgsqlTransaction tx = connInfo.m_Tx_PG;
cmdInsertUpdateDelete.Connection = conn;
cmdInsertUpdateDelete.Transaction = tx;
try
{
bError = false;
return cmdInsertUpdateDelete.ExecuteNonQuery();
}
catch (Exception ex)
{
WriteErrorLog(ex, connectionID);
AppLogger.LogFatal("Error executing ExecuteNonQuery method.\n" + cmdInsertUpdateDelete.CommandText, ex);
invalidateConnectionID(connectionID);
bError = true;
return -1;
}
finally
{
cmdInsertUpdateDelete.Transaction = null;
cmdInsertUpdateDelete.Connection = null;
}
}
Error Log

Command timeout with db2

I am trying to set timeout for a dbcommand, and test it that is why timeout is set to 1.
This is the code I am using but timeout never fires, am I doing something wrong?
NOTE: DbConnection is used because this code is an extract from a generic code used not only for db2 so db2connection is not an option.
String lProviderFactory = "System.Data.OleDb";
String lStrConexion = "Provider=IBMDADB2;Database=PYRAMID;Hostname=192.9.200.13;Protocol=TCPIP; Port=50000;Uid=db2admin;Pwd=xxx;";
String lQuery = "SLOW SELECT";
var lDbFactory = DbProviderFactories.GetFactory(lProviderFactory);
DbConnection mConexion = lDbFactory.CreateConnection();
mConexion.ConnectionString = lStrConexion;
mConexion.Open();
try
{
DbCommand lComando = mConexion.CreateCommand();
lComando.CommandText = lQuery;
lComando.CommandTimeout = 1;
DbDataAdapter lAdapter = lDbFactory.CreateDataAdapter();
lAdapter.SelectCommand = lComando;
DataSet lDs = new DataSet();
lAdapter.Fill(lDs);
}
catch(Exception ex)
{
Console.WriteLine("EXCEPCION :" + ex.Message); //Timeout should fall in here
}
finally
{
mConexion.Close();
}
Thanks!

Operation is not valid due to the current state of the object. in C#

I had created this method to check number of this record in the table
but it gives me this error message when the value of count(*) is 0
i use this library to connect oracle db
using Oracle.DataAccess.Client;
private int checkPort(int portID)
{
int intCount = 0;
try
{
OracleCommand oraCommand = new OracleCommand();
oraCommand.Connection = new DBManager().getConnection();
oraCommand.CommandText = "select count(*) as num from wireless_port_oid where port_id=:port_id";
oraCommand.Parameters.Add(":port_id", portID);
OracleDataReader Reader= oraCommand.ExecuteReader();
return intCount;
while (**Reader.Read()**)//it gives exception here
//The err Operation is not valid due to the current state of the object.
{
intCount =Convert.ToInt32(Reader[0]);
Reader.Close();
oraCommand.Connection.Close();
oraCommand = null;
if (intCount > 0)
{
return 1;
}
}
Reader.Close();
Reader.Dispose();
oraCommand.Connection.Close();
oraCommand.Connection.Dispose();
oraCommand.Dispose();
return 0;
}
catch (OracleException exception)
{
Console.WriteLine(exception.Message);
return 0;
}
}
You're closing the reader on Count = 0 and then trying to read it again in the while loop.
while (Reader.Read())//it gives exception here
//The err Operation is not valid due to the current state of the object.
{
intCount =Convert.ToInt32(Reader[0]);
Reader.Close();
oraCommand.Connection.Close();
oraCommand = null;
if (intCount > 0)
{
return 1;
}
// if intCOunt == 0 then what? loop again
}
But your code is not valid - I just noticed that you have a return intCount; just before the line you says has an error. I assume that that's just example typo.
I would refactor your code to take adavantage of C#'s using statement:
private int checkPort(int portID) {
string sql = "select count(*) as num from wireless_port_oid where port_id=:port_id";
int intCount = 0;
try {
using(OracleCommand oraCommand = new OracleCommand()) {
using(oraCommand.Connection = new DBManager().getConnection()) {
oraCommand.CommandText = sql;
oraCommand.Parameters.Add(":port_id", portID);
intCount = oraCommand.ExecuteScalar();
}
}
}
catch (OracleException exception) {
Console.WriteLine(exception.Message);
// may be you shouldn't return 0 here possibly throw;
}
return intCount;
}

Categories