Oracle error ORA-12571 encountered for Select Statement - c#

I'm trying to read table data from ORACLE with Parameter binding in c#. While executing the dataAdapter I'm getting ORA-12571 exception.
Below is my code for reading multiple data at the same time.
public DataTable SelectFromServer(string qualifiedDBName, DataTable dataTable) {
try
{
if (this.Con.State == ConnectionState.Closed)
{
this.OpenConnection();
}
DataTable resultTable = new DataTable();
dataTable.TableName = qualifiedDBName;
DbProviderFactory factory = DbProviderFactories.GetFactory(this.Con);
using (DbCommand command = factory.CreateCommand())
{
command.Connection = this.Con;
command.CommandText = this.GenerateSqlToSelect(factory,command,dataTable);
DbDataAdapter adapter = factory.CreateDataAdapter();
adapter.SelectCommand = command;
adapter.Fill(resultTable);
return resultTable;
}
}
catch (Exception exc)
{
throw exc;
}
}
Below is the method where I used to generate Select Query
private string GenerateSqlToSelect(DbProviderFactory factory, DbCommand command, DataTable table)
{
//var values1 = new List<string>();
var SelectQuery = new StringBuilder();
var data = table.ToArray();
var syntax = new OracleSyntax();
command.GetType().GetProperty("ArrayBindCount").SetValue(command, table.Rows.Count, null);
for (var i = 0; i < table.Columns.Count; i++)
{
var names = new StringBuilder();
var values = new StringBuilder();
var column = table.Columns[i];
OracleParameter parameter = new OracleParameter();
parameter.ParameterName = column.ColumnName;
parameter.Direction = ParameterDirection.Input;
parameter.DbType = column.DataType.GetDbType();
parameter.Value = data[i];
parameter.ArrayBindSize = GetDataLength(data[i]);
if (SelectQuery.Length > 0)
{
SelectQuery.Append(" and ");
}
names.AppendFormat("{0}", column.ColumnName);
values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);
SelectQuery.AppendFormat("{0} = {1}", names, values);
command.Parameters.Add(parameter);
}
string operationString = "SELECT * FROM";
string sqlQuery = string.Format("{0} {1} WHERE {2}", operationString, this.FormatByQuote(syntax,table.TableName), SelectQuery);
return sqlQuery;
}
private int[] GetDataLength(object[] objs)
{
List<int> dataLengthIterator = new List<int>();
foreach (object obj in objs)
{
dataLengthIterator.Add(obj.ToString().Length);
}
return dataLengthIterator.ToArray();
}
this.FormatByQuote() method is nothing but getting a quoted TableName.
Output of GenerateSqlToSelect() method is
SELECT * FROM "CUSTOMER_MASTER" WHERE USER_ID= :USER_ID and LINE_NUMBER = :LINE_NUMBER
The Query is generating based upon the DataTable input
Tried multiple workarounds but could not get the reason why the exception is occurring.

Related

How to sort a dataset in ASP.NET C#

I am trying to sort a datatable into a DataSet. I want to sort by the Status Column in "DESC". But I am not aware how to go about this. I have tried the suggested solutions online but I seem not to be doing something right. Here is what I have tried, albeit, I have commented out the sorting lines of the code as they do not work for me. How can I sort my table using the Status column in Desc?
[WebMethod(EnableSession = true)]
public List < TaskListClass > getTasks() {
var userId = Session["UserId"].ToString();
List < TaskListClass > objB = new List < TaskListClass > ();
try {
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConnString"].ToString())) {
connection.Open();
DataSet Myds = new DataSet();
// Myds.Tables[0].DefaultView.Sort = "Status desc";
SqlDataAdapter sqldr = new SqlDataAdapter();
string ProcName = "getTasks";
SqlCommand cmd = new SqlCommand(ProcName, connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#userId", SqlDbType.VarChar, 900).Value = userId;
sqldr.SelectCommand = cmd;
sqldr.Fill(Myds);
DataTable dt = Myds.Tables[0];
// DataTable dt = Myds.Tables[0].DefaultView.ToTable();
for (int i = 0; i < dt.Rows.Count; i++) {
objB.Add(new TaskListClass() {
Id = Convert.ToString(dt.Rows[i]["Id"]),
Subject = Convert.ToString(dt.Rows[i]["Subject"]),
Customer = Convert.ToString(dt.Rows[i]["Customer"]),
Sender = Convert.ToString(dt.Rows[i]["Sender"]),
Receiver = Convert.ToString(dt.Rows[i]["Receiver"]),
Priority = Convert.ToString(dt.Rows[i]["Priority"]),
StartDate = Convert.ToString(dt.Rows[i]["StartDate"]),
EndDate = Convert.ToString(dt.Rows[i]["EndDate"]),
Status = Convert.ToString(dt.Rows[i]["Status"]),
OnProgress = Convert.ToString(dt.Rows[i]["OnProgress"]),
});
}
}
} catch (Exception e) {
msg = e.ToString();
}
return objB;
}
Ok, a few things.
first up, a dataset is a collection of tables - "many tables" possible.
But you have ONE table, so why use a dataset? I see no need. Just use a single data table for this.
And this will reduce the code.
So, I suggest this, or close to this:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConnString"].ToString()))
{
using (var cmd = new SqlCommand("getTasks", connection))
{
connection.Open();
cmd.CommandType = CommandType.StoredProcedure;
DataTable dt = new DataTable();
cmd.Parameters.Add("#userId", SqlDbType.VarChar).Value = userId;
dt.Load(cmd.ExecuteReader());
// now sort the datatable
dt.DefaultView.Sort = "Status DESC";
// now fill out our object with each row
foreach (DataRow OneRow in dt.Rows)
{
objB.Add(new TaskListClass()
{
Id = OneRow["Id"].ToString(),
Subject = OneRow["Subject"].ToString(),
Customer = OneRow["Customer"].ToString(),
Sender = OneRow["Sender"].ToString(),
Receiver = OneRow["Receiver"].ToString(),
Priority = OneRow["Priority"].ToString(),
StartDate = OneRow["StartDate"].ToString(),
EndDate = OneRow["EndDate"].ToString(),
Status = OneRow["Status"].ToString(),
OnProgress = OneRow["OnProgress"].ToString(),
}); ;
}
}
}
}
return objB;
The way the current code is written, you could add this after the for-loop:
objB = objB.OrderByDescending(t => t.Status).ToList();
Depending of the datatype of Status, it might be sorted alphabetically.
var dataRow = dt.AsEnumerable().OrderByDescending(x => x.Field<string>("Status")).ToList();
foreach (var item in dataRow)
{
//Enter your Code Here
}
Here dt is your datatable.
dataRow is a set of list.
After get the data list, you can asign it to your "objB".

Return output parameter from C#

I have a procedure with 2 input parameters and 2 output parameters. Currently its working fine. However, i want to take the two output parameters of the procedure and store it in a variable. Can anyone guide me how.
Stored procedure code:
create or replace PROCEDURE P_LOGIN_USER
(
USERNAME IN VARCHAR2
, ENCRYPTIONKEY IN VARCHAR2
, OUT_STATUS OUT VARCHAR2
, OUT_STATUS_DESC OUT VARCHAR2
)
------------------------Procedure Code
END P_LOGIN_USER
C# Code where i assign the input parameters. Missing part is getting the output parameters
OracleCommand cmd = new OracleCommand("P_LOGIN_USER", OrCon);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter in_username = new OracleParameter();
in_username.OracleDbType = OracleDbType.Varchar2;
in_username.Direction = ParameterDirection.Input;
in_username.Size = 500;
in_username.Value = username;
cmd.Parameters.Add(in_username);
OracleParameter in_ecnryptionkey = new OracleParameter();
in_ecnryptionkey.OracleDbType = OracleDbType.Varchar2;
in_ecnryptionkey.Direction = ParameterDirection.Input;
in_ecnryptionkey.Size = 500;
in_ecnryptionkey.Value = password;
cmd.Parameters.Add(in_ecnryptionkey);
OracleParameter out_1 = new OracleParameter();
out_1.OracleDbType = OracleDbType.Varchar2;
out_1.Direction = ParameterDirection.Output;
out_1.Size = 500;
cmd.Parameters.Add(out_1);
OracleParameter out_2 = new OracleParameter();
out_2.OracleDbType = OracleDbType.Varchar2;
out_2.Direction = ParameterDirection.Output;
out_2.Size = 500;
cmd.Parameters.Add(out_2);
try
{
OrCon.Open();
cmd.ExecuteNonQuery();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "P_LOGIN_USER";
cmd.Parameters.Add(new OracleParameter
{
ParameterName = "result",
Size = 1,
Direction = ParameterDirection.ReturnValue,
OracleDbType = OracleDbType.Varchar2
});
}
catch (OracleException ex)
{
Console.Write(ex.Message);
}
OrCon.Close();
You can get the value out output parameter like this.
string outputStatus = Convert.ToString(cmd.Parameters["#OUT_STATUS "].Value);
Put the above line after ExecuteNonQuery()
Stored procedure code:
create or replace PROCEDURE P_LOGIN_USER
(
USERNAME IN VARCHAR2
, ENCRYPTIONKEY IN VARCHAR2
, p_recordset OUT SYS_REFCURSOR) IS
BEGIN
OPEN p_recordset FOR
SELECT OUT_STATUS ,OUT_STATUS_DESC .....
END
C#:
using (var reader = cmd.ExecuteReader())
{
List<ListModel> obj= reader.MapToList<ListModel>();
return obj;
}
## **MapToList** ##
public static List<T> MapToList<T>(this DbDataReader dr) where T : new()
{
if (dr != null && dr.HasRows)
{
var entity = typeof(T);
var entities = new List<T>();
var propDict = new Dictionary<string, PropertyInfo>();
var props = entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
propDict = props.ToDictionary(p => p.Name.ToUpper(), p => p);
List<string> log = new List<string>();
while (dr.Read())
{
try
{
T newObject = new T();
for (int index = 0; index < dr.FieldCount; index++)
{
var columnname = dr.GetName(index).ToUpper();
if (propDict.ContainsKey(dr.GetName(index).ToUpper()))
{
var info = propDict[dr.GetName(index).ToUpper()];
if ((info != null) && info.CanWrite)
{
try
{
var val = dr.GetValue(index);
info.SetValue(newObject, (val == DBNull.Value) ? null : val, null);
}
catch (Exception ex)
{
var columename= dr.GetName(index).ToUpper();
var val= dr.GetValue(index);
var getype = val.GetType();
log.Add(columename + ":" + val + ":" + getype.ToString());
}
}
}
}
entities.Add(newObject);
}
catch (Exception ex)
{
}
}
return entities;
}
return null;
}

C# When I execute a query dataTable is not loaded and the I obtain an expiration exeption

how are you ?
i have a problem loading data from DB (connexion string is good, since I can insert data into DB) into my data Table.
my query also works fine, when execute in Sql management studio I received 15 records... so after some lonely search and tries, I come to you.
Here is the code of my function supposed to get Value from DB.
The code stops at 'dt.Load(sqlCommand.ExecuteReader());' , where it seems to search, but i obtain after some seconds , a timeout exeption. And I as I
public List<string> GetConfigurationValues(string configurationKey, int? idBusinessUnit, int? idDomain)
{
string conn = ConnectionStringHelper.GetIdentityConnectionString();
List<string> conf = new List<string>();
using (SqlConnection dbConnection = new SqlConnection(conn))
{
dbConnection.Open();
SqlCommand sqlCommand = new SqlCommand(#"
SELECT Value
FROM ConfigurationValue cv
INNER JOIN ConfigurationFilter cf ON cv.idConfigurationValue = cf.idConfigurationValue
INNER JOIN ConfigurationKey ck ON ck.idConfigurationKey = cf.idConfigurationKey
WHERE ck.KeyName = #ConfigurationKey
AND((cf.idDomain = #idDomain) OR(cf.idDomain IS NULL))
AND((cf.idBusinessUnit = #idBusinessUnit) OR(cf.idBusinessUnit IS NULL))", dbConnection);
sqlCommand.CommandType = System.Data.CommandType.Text;
sqlCommand.Parameters.Add(new SqlParameter("#ConfigurationKey", "PORTAL_THEME"));
if (idBusinessUnit == null)
sqlCommand.Parameters.Add(new SqlParameter("#idBusinessUnit", null)); //DBNull.Value
else
sqlCommand.Parameters.Add(new SqlParameter("#idBusinessUnit", null));
if (idDomain == null)
sqlCommand.Parameters.Add(new SqlParameter("#idDomain", null));// DBNull.Value
else
sqlCommand.Parameters.Add(new SqlParameter("#idDomain", 281));
DataTable dt = new DataTable();
dt.Load(sqlCommand.ExecuteReader());
//dbConnection.Close();
if (dt != null)
if (dt.Rows.Count > 0)
foreach (DataRow dr in dt.Rows)
conf.Add(Convert.ToString(dr["Value"]));
}
return conf;
}
Try this:
SqlCommand sqlCommand = new SqlCommand(#"
SELECT Value
FROM ConfigurationValue cv
INNER JOIN ConfigurationFilter cf ON cv.idConfigurationValue = cf.idConfigurationValue
INNER JOIN ConfigurationKey ck ON ck.idConfigurationKey = cf.idConfigurationKey
WHERE ck.KeyName = #ConfigurationKey
AND((cf.idDomain = #idDomain) OR(cf.idDomain IS NULL))
AND((cf.idBusinessUnit = #idBusinessUnit) OR(cf.idBusinessUnit IS NULL))", dbConnection);
sqlCommand .CommandTimeout = 500;
thank you, for your kind attention.I solved it this morning. it was a probleme in the way I excecuted the load of the dataTable. Instead of a dataTable I am using now a DataReader. I precise, that if we use the dataReader, we get the right error message (it s a bonus.) So here is the part of the code I changed (for thoose who want to know) :
public List<string> GetConfigurationValues(string configurationKey, int? idBusinessUnit, int? idDomain)
{
string conn = ConnectionStringHelper.GetIdentityConnectionString();
string valueRes;
int idConfigurationKey = 0;
if (configurationKey == "PORTAL_THEME") { idConfigurationKey = 3; }
else if (configurationKey == "LOGO_THEME") { idConfigurationKey = 4; }
List<string> conf = new List<string>();
DataTable dt = new DataTable();
using (SqlConnection dbConnection = new SqlConnection(conn))
{
dbConnection.Open();
SqlCommand command = dbConnection.CreateCommand();
SqlTransaction transaction;
transaction = dbConnection.BeginTransaction("SampleTransaction");
command.Connection = dbConnection;
command.Transaction = transaction;
try
{
command.CommandText = #"
SELECT Value
FROM ConfigurationValue cv
INNER JOIN ConfigurationFilter cf ON cv.idConfigurationValue = cf.idConfigurationValue
INNER JOIN ConfigurationKey ck ON ck.idConfigurationKey = cf.idConfigurationKey
WHERE cf.idConfigurationKey = #ConfigurationKey
AND((cf.idDomain = #idDomain) OR(cf.idDomain IS NULL))
AND((cf.idBusinessUnit = #idBusinessUnit) OR(cf.idBusinessUnit IS NULL))";
command.CommandType = System.Data.CommandType.Text;
command.Parameters.Add(new SqlParameter("#ConfigurationKey", idConfigurationKey));
if (idBusinessUnit == null)
command.Parameters.Add(new SqlParameter("#idBusinessUnit", DBNull.Value)); //DBNull.Value
else
command.Parameters.Add(new SqlParameter("#idBusinessUnit", idBusinessUnit));
if (idDomain == null)
command.Parameters.Add(new SqlParameter("#idDomain", null));// DBNull.Value
else
command.Parameters.Add(new SqlParameter("#idDomain", idDomain));
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string theme = reader["Value"].ToString();
conf.Add(theme);
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
Console.WriteLine(" Message: {0}", ex.Message);
}
}
return conf;
}

.NET MySql batch Stored Procedure with Output Parameters

I'm trying to execute a batch call to a stored procedure to sync data between two systems. My SP has several in parameters and 1 out parameter. Everything works fine except I can't seem to get the out parameter.
I created a simplified sample that outlines my issue.
My Stored Procedure looks like this.
CREATE PROCEDURE `sampleProc`(IN i_val INT, OUT o_val INT)
BEGIN
SELECT i_val + i_val INTO o_val;
END
My .NET code
class TestingSP
{
public static void Test()
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("i_val", typeof(System.Int32)));
dt.Columns.Add(new DataColumn("o_val", typeof(System.Int32)));
for (int x = 1; x <= 100; x++)
{
DataRow dr = dt.NewRow();
dr["i_val"] = x;
dr["o_val"] = 0;
dt.Rows.Add(dr);
}
MySqlCommand command = new MySqlCommand();
command.CommandText = "sampleProc";
command.CommandType = CommandType.StoredProcedure;
command.UpdatedRowSource = UpdateRowSource.OutputParameters;
command.Parameters.Add("?i_val", MySqlDbType.Int32).SourceColumn = "i_val";
MySqlParameter output = new MySqlParameter();
output.ParameterName = "?o_val";
output.MySqlDbType = MySqlDbType.Int32;
output.Direction = ParameterDirection.Output;
output.SourceColumn = "o_val";
command.Parameters.Add(output);
MySqlConnectionStringBuilder conBuilder = new MySqlConnectionStringBuilder();
conBuilder.Server = "myserver";
conBuilder.UserID = "root";
conBuilder.Password = "password";
conBuilder.Port = 3308;
conBuilder.Database = "test_db";
Console.WriteLine("Rows: " + dt.Rows.Count);
using (MySqlConnection connection = new MySqlConnection(conBuilder.ConnectionString))
{
connection.Open();
command.Connection = connection;
using (MySqlDataAdapter da = new MySqlDataAdapter())
{
da.AcceptChangesDuringUpdate = true;
da.ContinueUpdateOnError = true;
da.UpdateCommand = command;
da.UpdateBatchSize = 50;
da.Update(dt);
foreach(var c in dt.GetErrors())
{
Console.WriteLine("Err: " + c.RowError);
}
foreach(DataRow row in dt.Rows)
{
Console.WriteLine("{0}: {1}", row["i_val"], row["o_val"]);
}
}
}
command.Dispose();
Console.WriteLine("Done...");
Console.ReadLine();
}
}
I've been scratching my head for a couple of days trying to get this to work but no matter what I try o_val is always zero.
Any help would be greatly appreciated.

"No value given for one or more required parameters." Access C# Simple Select

Error Returned:
"No value given for one or more required parameters."
String Array to pass to function:
String[,] arrParams = new String[1, 2] {
{"#ToUpper_user_id", id}
};
Value of id:
"test" (without the quotes)
SQL:
strSQL = "select * from users where ToUpper_user_id = ?;";
SQL Function Call:
if (jdb.getdb_data(strSQL, arrParams, strTableName, out dsGet, out strTechMessage))
{
...
}
Function that calls to get data from the db:
public static bool getdb_data(String strSQL, String[,] arrParams, String strTableName, out DataSet dsGet, out String strTechMessage)
{
bool boolRC = true;
String key = String.Empty;
String val = String.Empty;
dsGet = new DataSet();
strTechMessage = String.Empty;
String strSQL_Empty = String.Empty;
string connectionString = jdb.getConnString();
using (OleDbConnection connection =
new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(strSQL, connection);
if (arrParams.GetLength(0) > 0)
{
for (int i = 0; i < arrParams.GetLength(0); i++)
{
for (int j = 0; j < arrParams.GetLength(1); j++)
{
if (j.Equals(0)) { key = arrParams[i, j]; }
if (j.Equals(1)) { val = arrParams[i, j]; }
}
command.Parameters.AddWithValue(key, val);
}
}
else
{
boolRC = false;
strTechMessage = "No parameters found";
}
// Open the connection in a try/catch block.
// Create and execute the DataReader, writing the result
// set to the console window.
if (boolRC)
{
try
{
connection.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(strSQL, connection);
adapter.Fill(dsGet, strTableName);
}
catch (Exception ex)
{
boolRC = false;
strTechMessage = ex.Message;
}
}
}
return boolRC;
}
Please help - I think I am goin' insane! (The Update CRUD all works with parameters . . . just the select code is giving me the error.)
In "get_dbdata(...)" above, I should have have had:
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
instead of:
OleDbDataAdapter adapter = new OleDbDataAdapter(strSQL, connection);
In the code, both the sql and parameters have already been added to the command above.
Works now!

Categories