Cannot Update Row In Oracle DB Using C# Library - c#

When I want to update row with type 'date' in oracle database through asp.net C# method it gives the following error:
error:
ORA-00932: inconsistent datatypes: expected NUMBER got TIMESTAMP
code:
string query = String.Format("update mms_meetings m set m.end_date = :end_date where m.id = :id");
OracleCommand cmd = new OracleCommand("", GetDBConnection());
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
OracleParameter opId = new OracleParameter();
opId.DbType = DbType.Int32;
opId.Value = meetId;
opId.ParameterName = "id";
cmd.Parameters.Add(opId);
OracleParameter opDateEnd = new OracleParameter();
opDateEnd.DbType = DbType.DateTime;
opDateEnd.Value = dateEnd;
opDateEnd.ParameterName = "end_date";
cmd.Parameters.Add(opDateEnd);
cmd.ExecuteNonQuery();
cmd.Dispose();
CloseDBConnection();

1) You must send the exact format for your date as specified in your table column. Check default format for your date column. Like
'yyyy/MM/dd'
2) If you are using OleDb or ODBC Connection, they both use positional parameters so order of adding the parameters is very important. Try changing the order of your parameter to see if it helps.

Related

How to get output parameter and also a table when executing a stored procedure

Scenario
I'm working with SQL Server 2017 (not possible to change)
I'm using Visual Studio 2019 in C# console and .NET Framework 4.5 (possible to change)
I'm using ADO.NET because several years before we couldn't use Entity Framework, as the system is made to work with a stored procedure that returns at least 100k rows (possible to change)
Situation
I have an USP that returns a table that is at least 100k of rows by 20 fields. I need to add an output parameter in order to get also an ID created by the USP itself. So, the situation is that I need return a table and an ID (called ProcMonitorId). I don't know if this is even so possible (See workarounds section)
At the SQL level is seems to be so far so good:
CREATE PROCEDURE [myschema].[mystore]
#ProcMonitorId BIGINT OUTPUT
AS
BEGIN
BEGIN TRANSACTION
(...)
SELECT fields FROM myTable
SELECT #ProcMonitorId = #internalVariable
SQL execution:
And at repository layer (only relevant lines, someone were surprised for health of example):
var command = new SqlCommand("myStoreProcedure", mycon);
command.CommandType = CommandType.StoredProcedure;
SqlParameter outPutParameter = new SqlParameter();
outPutParameter.ParameterName = "#ProcMonitorId";
outPutParameter.SqlDbType = System.Data.SqlDbType.BigInt;
outPutParameter.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(outPutParameter);
// Open connection etc-etc that works
SqlDataAdapter da = new SqlDataAdapter(command);
DataTable dt = new DataTable();
string ProcMonitorId = outPutParameter.Value.ToString();
da.Fill(dt);
Everything worked fine until the addition of the output at C# level. It returns in the line:
string ProcMonitorId = outPutParameter.Value.ToString();
it returns NullReferenceException because Value is null (that can't be) and of course, can't convert to String. I would solve this situation by adding a ? but if that's situation happens for real, I need catch it any way as error. The main idea is that Value can not be null.
As I don't have any ORM map, (and my expertise is not ADO.NET but Entity Framework) I can't understand why is null (No, is not null at SQL layer, always return a value)
Question
How can I solve this error or how can I return a BIGINT parameter and ALSO a table result?
Workarounds
As I first glance I have to solve it quickly, I made a:
SELECT 1 as type, #procID as procid, null as data1, null as data2
UNION ALL
SELECT 2 as type, null as procid, data1, data2
in order to simulate a "header" and "data" rows on one single table.
But I don't like this solution and is not very elegant and flexible. I've to parse the header every time.
Thanks in advance and please comment anything, tip, help, workaround, I will be glade to update my answer if more information is needed.
Also I can make my Framework to .NET Core or change to Entity Framework. That I can't change is my SQL version
Update #2
No changes in SQL - Still working as screenshot
In C# - Hangs out for ever
SqlConnection connection = new SqlConnection(ConfigurationManager.AppSettings["DbConnection"]);
connection.Open();
var command = new SqlCommand("myUSP", connection);
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = Convert.ToInt16(ConfigurationManager.AppSettings["DataBaseTimeOut"]);
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
SqlParameter r = command.Parameters.Add("#ProcMonitorId", SqlDbType.BigInt);
r.Direction = ParameterDirection.Output;
DataTable dt = new DataTable();
using (var rdr = command.ExecuteReader())
{
dt.Load(rdr);
long id = (long)r.Value;
}
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
The parameter value won't be available until after you consume the resultset, eg
var cmd0 = new SqlCommand("create or alter procedure pFoo #id int output as begin select * from sys.objects; set #id = 12; end", con);
cmd0.ExecuteNonQuery();
var cmd = new SqlCommand("pFoo", con);
cmd.CommandType = CommandType.StoredProcedure;
var p1 = cmd.Parameters.Add("#id", SqlDbType.Int);
p1.Direction = ParameterDirection.Output;
var dt = new DataTable();
using (var rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
var id = (int)p1.Value;
}
You should use a Parameter with the Direction property set to ReturnValue, and, inside the sp, declare an internal variable and set it to the value you want.
Then call the RETURN statement before leaving the StoredProcedure.
As an example, see this SP:
ALTER PROCEDURE [GetTimeZoneGMT]
#TimeZone NVARCHAR(128)
AS
BEGIN
DECLARE #timeZoneNumber as INT = -20;
IF #TimeZone ='Pacific/Midway'
SET #timeZoneNumber = -11
ELSE IF #TimeZone ='Pacific/Niue'
SET #timeZoneNumber = -11
ELSE IF #TimeZone ='Pacific/Pago_Pago'
SET #timeZoneNumber = -11
SELECT 1 -- or whatever you need to have as result set
RETURN #timeZoneNumber;
END
The stored procedure ends with a (bogus) SELECT statement but also has a RETURN statement with the parameter set inside the SP logic.
Now from the C# side you could call it in this way (LinqPad example)
using (var connection = new SqlConnection("Data Source=(LOCAL);Initial Catalog=LinqPADTest;Integrated Security=True;"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("GetTimeZoneGMT", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#TimeZone", SqlDbType.NVarChar).Value = "Asia/Kuala_Lumpur";
SqlParameter r = cmd.Parameters.Add("#p2", SqlDbType.BigInt);
r.Direction = ParameterDirection.ReturnValue;
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
r.Value.Dump(); // Prints -20
dt.Dump(); // Prints a row with a single column with 1 as value
}

Delete data from Access using SQL Query - C#

\I have three columns in an access database table (DATA) as shown below
I just want to delete some rows based of two conditions in the WHERE clause in the SQL query ; for ex, delete row when NAME = "A" and Date = "1/1/2017"
I used DELETE from DATA Where Name='A' and Date='1/1/2017'
This gives "type mismatch error"!
Here is the code in C#:
using (OleDbConnection thisConnection = new OleDbConnection(connectionname))
{
string deletequery = " DELETE FROM DATA WHERE [Name] = 'A' And [Date] = '1/1/2017';
OleDbCommand myAccessCommandDelete = new OleDbCommand(deletequery, thisConnection);
thisConnection.Open();
myAccessCommandDelete.ExecuteNonQuery();
thisConnection.Close();
}
The best way to pass values to a database engine that will be used in a query is through the parameters collection specifying exactly the type of the parameter
using (OleDbConnection thisConnection = new OleDbConnection(connectionname))
{
string deletequery = #"DELETE FROM DATA WHERE [Name] = #name And
[Date] = #date";
OleDbCommand myAccessCommandDelete = new OleDbCommand(deletequery, thisConnection);
thisConnection.Open();
myAccessCommandDelete.Parameters.Add("#name", OleDbType.VarWChar).Value = "A";
myAccessCommandDelete.Parameters.Add("#date", OleDbType.Date).Value = new DateTime(2017,1,1);
myAccessCommandDelete.ExecuteNonQuery();
// not needed -> thisConnection.Close();
}
In this way you don't leave space to interpretation (conversion from string to date) of your values but you tell exactly to your db engine what your value is. And of course if you specify the correct type you can't have a Type Mismatch error

Oledb Exception 'No value given for one or required parameter C# update query

I'm trying to update some table columns. However, I'm getting the following exception during execution, and I don't know why:
'No value given for one or required parameter C# update query'
This is the code in question:
string qry = "UPDATE party_mast SET party_id_no = #partyID, contact_persn = #pContactPersn, tinno = #pTin, Phone_no = #pPhone, Fax_No = #pFax, E_mail = #pEmail, address = #pAddress, disc = #pDisc, pnote = #pNote WHERE party_name='"+name+"'";
OleDbCommand cm = new OleDbCommand(qry, cn);
cm.Parameters.AddWithValue("#partyID",pCst.Text);
cm.Parameters.AddWithValue("#pContactPersn,", pConatctPer.Text);
cm.Parameters.AddWithValue("#pTin", pTin.Text);
cm.Parameters.AddWithValue("#pFax", pFax.Text);
cm.Parameters.AddWithValue("#pEmail", pEmail.Text);
cm.Parameters.AddWithValue("#pAddress", pAdddress.Text);
cm.Parameters.AddWithValue("#pDisc", pDisc.Text);
cm.Parameters.AddWithValue("#pNote ", pNote.Text);
int x = cm.ExecuteNonQuery();

Pass a parameter to a stored procedure in AS400 to match IN keywork

I am trying to pass as parameter to a stored procedure as string that will match the IN syntax.
I defined the parameter as CHARACTER and if I am writing the following it works:
MPROMY IN ( '2','3' )
MPROMY is the column in the database table.
I am trying to replace the values with the parameter:
MPROMY IN ( PRIORDAYS )
PRIORDAYS is the parameter passed in.
Here is my code in C#:
var daysIn = "'2','3'";
return CallStoredProcedure(string.Format("CALL SPORDCMP('{0}')", daysIn));
I am getting the following error:
ERROR [42000] [IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0104 - Token 1 was not valid. Valid tokens: ) ,.
What is the correct syntax to pass a parameter in order to work with IN keyword?
This is how I've done it. In my case I am passing a store number (will not be hard coded when in production).
I build the command. Tell it the parms. Execute the stored procedure.
using IBM.Data.DB2.iSeries;
//Create a command object
cmd.Transaction = trans;
cmd.CommandText = "libraryname.storedprocedurename";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
ItemStoreNumber and ItemDesc are described in the model.
// Build the Stored Procedure Paramaters - Build Input Value
iDB2VarChar stNumber = "0001"; //Get from store later
iDB2Parameter parm = cmd.Parameters.Add("#ItemStoreNumber",
iDB2DbType.iDB2VarChar);
cmd.Parameters["#ItemStoreNumber"].Direction =
parameterDirection.Input;
cmd.Parameters["#ItemStoreNumber"].Value = stNumber;
DataTable dt = new DataTable();
iDB2DataAdapter da = new iDB2DataAdapter();
da.SelectCommand = cmd;
da.Fill(dt);
foreach (DataRow row in dt.Rows)
{
StoreItem storeitem = new StoreItem();
storeitem.ItemStoreNumber = (String)
row["RSTORE"].ToString();
storeitem.ItemDesc = (String) row["IDESC"].ToString();
storeitem.ItemUpc = (String)row["RUPC"].ToString();
storeitem.ItemUom = (String)row["ISUNIT"].ToString();
storeitem.ItemRpack = (String)row["RCPACK"].ToString();
storeitem.ItemRetailPrice =
Convert.ToDecimal(row["RCRETAILP"].ToString());
myStoreItems.Add(storeitem);
}
return myStoreItems;

Issue in fetching data from SP (Oracle Database)

As I am new to this, I am facing some issue in executing stored procedure in oracle DB. Here is the SP which gives record as output parameter which is of type %rowtype and l_serno as input parameter which is of type Number.
Create OR Replace procedure get_product(l_serno in product.serno%type,record out product%rowtype)
is
begin
select * into record from product where serno=l_serno;
end get_product;
Using C#, I am trying to fetch the data from the SP and show it on the gridview.
OracleCommand cmd = new OracleCommand("get_product", Conn);
cmd.CommandType = CommandType.StoredProcedure;
Conn.Open();
OracleParameter input = cmd.Parameters.Add("V_SERNO", OracleType.Number);
OracleParameter output = cmd.Parameters.Add("ITEMS_CURSOR", OracleType.Cursor);
input.Direction = ParameterDirection.Input;
output.Direction = ParameterDirection.ReturnValue;
input.Value = 2;
OracleDataReader rd = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rd);
GridView1.DataSource = dt;
GridView1.DataBind();
Conn.Close();
Here I am getting error as
ORA-06550: line 1, column 24:
PLS-00306: wrong number or types of arguments in call to 'GET_PRODUCT'
ORA-06550: line 1, column 7:
Please let me know what is the wrong I am doing here.
Thanks in Advance.
Your procedure has this signature:
(l_serno in product.serno%type,record out product%rowtype)
But in your C# code you specify this:
OracleParameter output = cmd.Parameters.Add("ITEMS_CURSOR", OracleType.Cursor);
A cursor is a pointer to a result set and is different from a variable. You could change your C# code: define a class whose attributes match the projection of the PRODUCT table. Alternatively, change the stored procedure to use a ref cursor.
The second approach is probably less work (not least because you can get us to do it for you)
create or replace procedure get_product
(l_serno in product.serno%type,
record out sys_refcursor)
is
begin
open record for
select * from product
where serno=l_serno;
end get_product;

Categories

Resources